mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-15 19:32:21 +02:00
refactor(notes): decompose Notes into feature-owned modules (#6713)
* refactor(notes): decompose Notes into feature-owned modules * fix(notes): avoid HTML interpolation in reminder picker * docs(notes): drop checkpoint archives, session logs and publication drafts The N0-N6 tarballs and raw pytest/node logs are not read by any script or test, and the logs carry absolute home-directory paths. Once squashed into dev they would stay in history for good. notes-pr.md and notes-issue.md were the drafts used to open #6712 and #6713, not documentation. notes-validation.md keeps the counts, the checkpoint hashes and implementation.sha256 as the record; local interpreter paths and the local Docker image name are replaced with portable placeholders. * fix(notes): keep the state store raw and stop masonry re-observing after close - state: writes built from views (filter, spread, splice) stored nested read-only views in the store, so structuredClone on a stored note threw DataCloneError. Store writes now unwrap nested views. - layout: a save that resolves after closePanel re-renders the leaving pane and re-created the masonry ResizeObserver that teardown had disposed. Skip creating it once Notes is closed. - index.js: drop 30 imported or declared names that were never used and group the imports at the top. Import order is unchanged. - Revert unrelated punctuation edits in .gitattributes and keep the header comment and docstring first in compare/vote.js and test_notes_dom_xss_helpers.py. Both fixes have a node test that fails on the previous head. * test(notes): make script rejection assertion case-insensitive Address CodeQL js/bad-tag-filter alert #1150 in test-only assertion and refresh Notes evidence manifest checksum. --------- Co-authored-by: Léo <leograndcontact@gmail.com>
This commit is contained in:
co-authored by
Léo
parent
9f8eae72fd
commit
f1a47f3812
@@ -0,0 +1,112 @@
|
||||
53dfddd71f02a9a60df42e3fb045bd1a80919d50870c0b77afe18a853f485bea .gitattributes
|
||||
867c6a4b025fefecb6ac4a91a38563a36107d9653599f64685e16a5be4fe7727 frontend/modules.json
|
||||
76de35ac93d72edb5dcd295e85c704af9b3f08c2fe9fdc56e0bcbebd4b322fd8 frontend/src/features/notes/application/agentActions.js
|
||||
37021f9643f6a3299d36b6021783a559e60ad84848ac2b12f0980b5034b6b9c4 frontend/src/features/notes/application/cardOperations.js
|
||||
fe3033db6ef316c6b15c6b01c0f202ee76a61ea2c5b6952b20144660ff17eb54 frontend/src/features/notes/application/checklistOperations.js
|
||||
85fc592724524bb5ff37d7e5e58a68fda9d7e645810b6c87a2d4dd3cb41f9dd5 frontend/src/features/notes/application/deletion.js
|
||||
ce38e7976ee315b198baebffe45f9a1f4e63d87affd9898ed5cf4bde37b903e7 frontend/src/features/notes/application/drafts.js
|
||||
6210915184c30f73911f144fe0d12a9935d6f2ce42cb2aaf6aeaa75614ca51a2 frontend/src/features/notes/application/queries.js
|
||||
0da923790f4036d5fe354df4e529feb4b96e178495cb951f269093c0a8347e4e frontend/src/features/notes/application/reminders.js
|
||||
8f95d086fc2e60beae32b9e9debba41b35448e1c5b4ac78e4989652ef2d44e35 frontend/src/features/notes/application/selection.js
|
||||
4ceb424b3b6e30a5f507804f42051be02390d4ce1f03ef284094e48825cde5c3 frontend/src/features/notes/application/state.js
|
||||
1c5d5af833aab91f71a34c11535885eb7bf9f751de5aa89f79defe0f696f20fb frontend/src/features/notes/application/submission.js
|
||||
1d58ea2d495c8d301c550eb9ba7f627c515a8784bcd105558d941522965e77b0 frontend/src/features/notes/application/workflows.js
|
||||
9ddbfb20e0a5564dd83365ad498286d68ef03fd60d632619ad4d9656e2f73c95 frontend/src/features/notes/domain/noteRules.js
|
||||
946ef7a98b0a2dbe329e8259250af11a11702c74fd997e17fb3aff007fbe40c9 frontend/src/features/notes/domain/recurrence.js
|
||||
25cf3a1cef5dbac0840aef513ffa010a9b08d206de96ce2527e6159a5454b555 frontend/src/features/notes/index.js
|
||||
8b186bbfbb003b8d738c80713e1cbb5c6924ee14119929c5ea65707b46076b0c frontend/src/features/notes/infrastructure/http.js
|
||||
c7552d1f4600ae721437892fc0a1e5a0332abe30082bd943cd13a379c9514fec frontend/src/features/notes/infrastructure/notifications.js
|
||||
ff91a55c55fbdd876c69d9ec10e4e992104c95b6d12d752d9745193fccbc646a frontend/src/features/notes/infrastructure/storage.js
|
||||
4ff6d69d04547a0325041f774c3bf0707d8b67982d59a221127e07dc9b01383c frontend/src/features/notes/ui/cardChecklist.js
|
||||
dd87f1929ef8a5d57fdf1ddb12a0a6be53d95be07946be54f946c6fe31ef80bc frontend/src/features/notes/ui/cardInteractions.js
|
||||
4ff661a65d88e810f346260a354070dba325d6beaa57d1c4e82e8bf09b894538 frontend/src/features/notes/ui/cardRendering.js
|
||||
113d4457f25291d15afb7fb6775ea063f24c9dac51bb0d262787c9e40705235b frontend/src/features/notes/ui/cardReorder.js
|
||||
eecafbd92076209fa41826820125fbe9ffa757d6d1bff018e9acc2ede2a18e72 frontend/src/features/notes/ui/checklist.js
|
||||
155ea3d70e653f38a62ff50fc5be6aee019d42e86d28753da9edb258ac7c93e1 frontend/src/features/notes/ui/checklistReorder.js
|
||||
5462fea63a2aa9d1fc07dca91b462f6ff24f352b05d99ea6feb437469c0e1f3e frontend/src/features/notes/ui/clipboard.js
|
||||
2619e5f8b15eb3057330ef220abe6bc354a496effc0df3d89385cdfef9242c86 frontend/src/features/notes/ui/colors.js
|
||||
11cf24e7e8e8954d764cb58d786fa6f6d71f84f1c6c5ba644d761e28cfdbaedf frontend/src/features/notes/ui/draftEditor.js
|
||||
f55d4eff7f550e183ecf240a45002936063dbb4eae153e11834da4cb6bd13d35 frontend/src/features/notes/ui/drawing.js
|
||||
f85c86e70b3a380449fe3c7ecc7a4e68946de320523f5edc8e33f8eab3f0a02a frontend/src/features/notes/ui/editor.js
|
||||
3946b8324ad8f0212621e526479668308e48b799bf0dbb608e5cd4626f6c1f03 frontend/src/features/notes/ui/filters.js
|
||||
a893d09e96fb98d13db8ae5c3fb8c5e7a040c62031dd961396a18b7ae2a82a38 frontend/src/features/notes/ui/layout.js
|
||||
8d8c62a87d4df134d3b9dd97eaf59d02c52f1a38f6bc2e109e8426081d453a8d frontend/src/features/notes/ui/lifecycle.js
|
||||
62ad9408cb139143168f2c5834ec56b83264c4daed3e84fa9b4b0a281712144c frontend/src/features/notes/ui/mobileEditor.js
|
||||
2a3ccbad103dcc880e4baf2b3aa3ece4df7b73752bd30078185f03227585148f frontend/src/features/notes/ui/mobileReorder.js
|
||||
856fe945cf697278f795b8753704119839fa12bc5e0e69e9dab57c4b4dd6d24e frontend/src/features/notes/ui/panel.js
|
||||
8aa081cb7341d9a67ef46c74da49aebd729e9b53a73d618b81c89566c874b507 frontend/src/features/notes/ui/quickAdd.js
|
||||
8a4f23a013f06876894e6544b49540b288007d0d7e4cddca955978588f47a64a frontend/src/features/notes/ui/reminderDisplay.js
|
||||
cb043be801ab40cf8141af6ff1ad788e69fef57a87960ca992071ad9ad29ad90 frontend/src/features/notes/ui/reminderPicker.js
|
||||
38f12ba7771589aa427f054f48919569dcee9abe0246e02b9767202adb854cdc frontend/src/features/notes/ui/selection.js
|
||||
2634f252b2899e2e70fc9fec37144b0cc9b0ed00724da81bfef74b1acf7c05b6 frontend/src/features/notes/ui/text.js
|
||||
d2655ef163825ce6c40d8ef46bc9dfc63a2aa19fb1a7e10b28002f79cb0db409 frontend/src/features/notes/ui/toolbar.js
|
||||
a0aa203e87814d0eebebb6b049776c3efd576f4a5c6e17e486c8a2893c9c21df frontend/src/features/notes/ui/windowLayout.js
|
||||
68f0cbe07c7b61fcaf92920cd47042c576ab27fd9553c971cff45c595c25d80a frontend/src/shared/ui/confetti.js
|
||||
c16fcde607dce2f10a1afd1f8845403a7d0b97a9d5a67ec7aa329c367ba585e8 scripts/verify_frontend_runtime.py
|
||||
c2e5de2b8ce168220bad4fcefed710e60eeb0dd3e992e76cd980f2c0ca52815a scripts/verify_notes_browser_runtime.py
|
||||
fa31d673c40f973490e9fac52130b4a915b944a7abdd217a9bd8d57e66d57ca6 static/js/compare/vote.js
|
||||
76de35ac93d72edb5dcd295e85c704af9b3f08c2fe9fdc56e0bcbebd4b322fd8 static/js/features/notes/application/agentActions.js
|
||||
37021f9643f6a3299d36b6021783a559e60ad84848ac2b12f0980b5034b6b9c4 static/js/features/notes/application/cardOperations.js
|
||||
fe3033db6ef316c6b15c6b01c0f202ee76a61ea2c5b6952b20144660ff17eb54 static/js/features/notes/application/checklistOperations.js
|
||||
85fc592724524bb5ff37d7e5e58a68fda9d7e645810b6c87a2d4dd3cb41f9dd5 static/js/features/notes/application/deletion.js
|
||||
ce38e7976ee315b198baebffe45f9a1f4e63d87affd9898ed5cf4bde37b903e7 static/js/features/notes/application/drafts.js
|
||||
6210915184c30f73911f144fe0d12a9935d6f2ce42cb2aaf6aeaa75614ca51a2 static/js/features/notes/application/queries.js
|
||||
0da923790f4036d5fe354df4e529feb4b96e178495cb951f269093c0a8347e4e static/js/features/notes/application/reminders.js
|
||||
8f95d086fc2e60beae32b9e9debba41b35448e1c5b4ac78e4989652ef2d44e35 static/js/features/notes/application/selection.js
|
||||
4ceb424b3b6e30a5f507804f42051be02390d4ce1f03ef284094e48825cde5c3 static/js/features/notes/application/state.js
|
||||
1c5d5af833aab91f71a34c11535885eb7bf9f751de5aa89f79defe0f696f20fb static/js/features/notes/application/submission.js
|
||||
1d58ea2d495c8d301c550eb9ba7f627c515a8784bcd105558d941522965e77b0 static/js/features/notes/application/workflows.js
|
||||
9ddbfb20e0a5564dd83365ad498286d68ef03fd60d632619ad4d9656e2f73c95 static/js/features/notes/domain/noteRules.js
|
||||
946ef7a98b0a2dbe329e8259250af11a11702c74fd997e17fb3aff007fbe40c9 static/js/features/notes/domain/recurrence.js
|
||||
25cf3a1cef5dbac0840aef513ffa010a9b08d206de96ce2527e6159a5454b555 static/js/features/notes/index.js
|
||||
8b186bbfbb003b8d738c80713e1cbb5c6924ee14119929c5ea65707b46076b0c static/js/features/notes/infrastructure/http.js
|
||||
c7552d1f4600ae721437892fc0a1e5a0332abe30082bd943cd13a379c9514fec static/js/features/notes/infrastructure/notifications.js
|
||||
ff91a55c55fbdd876c69d9ec10e4e992104c95b6d12d752d9745193fccbc646a static/js/features/notes/infrastructure/storage.js
|
||||
4ff6d69d04547a0325041f774c3bf0707d8b67982d59a221127e07dc9b01383c static/js/features/notes/ui/cardChecklist.js
|
||||
dd87f1929ef8a5d57fdf1ddb12a0a6be53d95be07946be54f946c6fe31ef80bc static/js/features/notes/ui/cardInteractions.js
|
||||
4ff661a65d88e810f346260a354070dba325d6beaa57d1c4e82e8bf09b894538 static/js/features/notes/ui/cardRendering.js
|
||||
113d4457f25291d15afb7fb6775ea063f24c9dac51bb0d262787c9e40705235b static/js/features/notes/ui/cardReorder.js
|
||||
eecafbd92076209fa41826820125fbe9ffa757d6d1bff018e9acc2ede2a18e72 static/js/features/notes/ui/checklist.js
|
||||
155ea3d70e653f38a62ff50fc5be6aee019d42e86d28753da9edb258ac7c93e1 static/js/features/notes/ui/checklistReorder.js
|
||||
5462fea63a2aa9d1fc07dca91b462f6ff24f352b05d99ea6feb437469c0e1f3e static/js/features/notes/ui/clipboard.js
|
||||
2619e5f8b15eb3057330ef220abe6bc354a496effc0df3d89385cdfef9242c86 static/js/features/notes/ui/colors.js
|
||||
11cf24e7e8e8954d764cb58d786fa6f6d71f84f1c6c5ba644d761e28cfdbaedf static/js/features/notes/ui/draftEditor.js
|
||||
f55d4eff7f550e183ecf240a45002936063dbb4eae153e11834da4cb6bd13d35 static/js/features/notes/ui/drawing.js
|
||||
f85c86e70b3a380449fe3c7ecc7a4e68946de320523f5edc8e33f8eab3f0a02a static/js/features/notes/ui/editor.js
|
||||
3946b8324ad8f0212621e526479668308e48b799bf0dbb608e5cd4626f6c1f03 static/js/features/notes/ui/filters.js
|
||||
a893d09e96fb98d13db8ae5c3fb8c5e7a040c62031dd961396a18b7ae2a82a38 static/js/features/notes/ui/layout.js
|
||||
8d8c62a87d4df134d3b9dd97eaf59d02c52f1a38f6bc2e109e8426081d453a8d static/js/features/notes/ui/lifecycle.js
|
||||
62ad9408cb139143168f2c5834ec56b83264c4daed3e84fa9b4b0a281712144c static/js/features/notes/ui/mobileEditor.js
|
||||
2a3ccbad103dcc880e4baf2b3aa3ece4df7b73752bd30078185f03227585148f static/js/features/notes/ui/mobileReorder.js
|
||||
856fe945cf697278f795b8753704119839fa12bc5e0e69e9dab57c4b4dd6d24e static/js/features/notes/ui/panel.js
|
||||
8aa081cb7341d9a67ef46c74da49aebd729e9b53a73d618b81c89566c874b507 static/js/features/notes/ui/quickAdd.js
|
||||
8a4f23a013f06876894e6544b49540b288007d0d7e4cddca955978588f47a64a static/js/features/notes/ui/reminderDisplay.js
|
||||
cb043be801ab40cf8141af6ff1ad788e69fef57a87960ca992071ad9ad29ad90 static/js/features/notes/ui/reminderPicker.js
|
||||
38f12ba7771589aa427f054f48919569dcee9abe0246e02b9767202adb854cdc static/js/features/notes/ui/selection.js
|
||||
2634f252b2899e2e70fc9fec37144b0cc9b0ed00724da81bfef74b1acf7c05b6 static/js/features/notes/ui/text.js
|
||||
d2655ef163825ce6c40d8ef46bc9dfc63a2aa19fb1a7e10b28002f79cb0db409 static/js/features/notes/ui/toolbar.js
|
||||
a0aa203e87814d0eebebb6b049776c3efd576f4a5c6e17e486c8a2893c9c21df static/js/features/notes/ui/windowLayout.js
|
||||
7f1a7961d586767298672fad71a0d627389e185f0fb28792a04d0b987e1d5c5c static/js/notes.js
|
||||
68f0cbe07c7b61fcaf92920cd47042c576ab27fd9553c971cff45c595c25d80a static/js/shared/ui/confetti.js
|
||||
97fd43c17f3cb1928947e24159a3b59dc81ef7dca95862e8a47154e9cb732f88 static/sw.js
|
||||
910cd5777564e9f6338b8a864a772beffea197dc476464171c180e7be96e572d tests/browser/notesNative.mjs
|
||||
ef4bc40a710919c81c582d3b9fe80376d0d5ae66fb9be3c293871a83ee360f97 tests/browser/notesOffline.mjs
|
||||
437ec2e9865b3e066bbec8d7595a0d947f1e503b96e7b4d819ec1bed86c9bb1e tests/browser/notesReference.mjs
|
||||
9af973a5d2fb08a5eed550be0198bef501af56802c3844b5d0bb8e718cc685cf tests/fixtures/notesRecurrenceBaseline.mjs
|
||||
859a5f442dc717f59993891c338cd6ae9d6e5e009392a2ee69ab0e3b063bb572 tests/helpers/notes_source.py
|
||||
739ffc3f20de8e2bdf1d513b17bf485f85821e9906109cdf8ffea04b81b0f1dd tests/notesApplication.test.mjs
|
||||
1946369be43177b19a44cd9ae4f90d64da6558d1a470f8e347b490a2188782be tests/notesCharacterization.test.mjs
|
||||
99f0cd92a30cf01c0ee6814f6684edeb80ebdb9a5ab96583244092865bfb6212 tests/notesDraftAutosave.test.mjs
|
||||
0417205809de16c7c7338ea80ba19ca844603b3e06655987226f5f83d962d18b tests/notesInfrastructure.test.mjs
|
||||
dcf7c2d33de9bb457f96af070354ecc3ab69669002bdc9c7c943bef1b3d2e9bc tests/notesRecurrence.test.mjs
|
||||
dd9a703465dde8f92625a3226ab52d20a02aa5d3415fbcc70609f69a372ccc12 tests/notesReminders.test.mjs
|
||||
5a9112569f226525faaf6603a9867620b47902534f9cd882c08f71f2f96614b2 tests/notesWorkflows.test.mjs
|
||||
35fb2bd1f02757b73188342ec00f1e97253b8ba8dfb577861675872a517bd949 tests/selectedNotesContext.test.mjs
|
||||
c6c64c2b695b84d00f8a80a980be00766175c482548c86484f991ef671ecfbe9 tests/test_notes_document_mutual_minimize.py
|
||||
02c2aeb856798d982e5debcb9c605172933b0216a039cf0d96cdd415b1e2ef83 tests/test_notes_dom_xss_helpers.py
|
||||
5a511c7a2ef5d28463df34f3462db9ce59575d624cf8181577bab2cc371b4f9f tests/test_notes_mobile_checklist_toggle_static.py
|
||||
1db10a0d344818459d64279da807ddefe9b866dfe560ac4b154b486dd1a5efc0 tests/test_notes_reference_browser.py
|
||||
49f466b1a717098aa25439b6ff9ef3ae3d027d9dd976212b165b0b99a582b952 tests/test_notes_reference_contracts_js.py
|
||||
c2d877a11eafcb99b24a1c89111e5df4453a62bc8cf7d26ae1118b25c4a5ace4 tests/test_notes_search_reset_on_reopen_js.py
|
||||
6d95f073421427b5e149ef1e85c8b5749095d00337f05960134552985f73e372 tests/test_notes_select_esc_listener_js.py
|
||||
b3118a4b40fcfcbb26ad9ccbcb332fc6ced873d8cad1160be38a286ad1e664a4 tests/test_notes_sidebar_new_note.py
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -1,9 +1,10 @@
|
||||
# Odysseus frontend architecture handbook
|
||||
|
||||
Status: F1 foundation and continuation guide, pending review. The final Notes
|
||||
reference case study belongs to the comprehensive Notes draft PR; the recipient
|
||||
handoff follows its integration. This document must evolve with reviewed internal
|
||||
checkpoints and distinguish executed work from proposals.
|
||||
Status: F1 merged in PR #6701. The complete Notes reference is implemented as an
|
||||
unpublished review diff on `refactor/notes-reference-decomposition`. Read its
|
||||
[case study](notes-case-study.md), [module inventory](notes-module-inventory.md)
|
||||
and [validation receipts](notes-validation.md). Publication and the recipient's
|
||||
post-integration reproduction remain pending.
|
||||
|
||||
Read the [ADR](ADR-001-source-and-deployment.md), [assessment](assessment.md),
|
||||
[validation report](validation.md) and [Notes roadmap](notes-roadmap.md).
|
||||
@@ -90,6 +91,13 @@ existing objects and initialization timing when extracting a stateful module.
|
||||
Do not instantiate a new store in both the legacy facade and the feature API.
|
||||
Compatibility facades only forward the same live implementation.
|
||||
|
||||
The Notes reference uses internal read-only live views to preserve captured note
|
||||
identity across existing asynchronous completions. Its state owner supplies all
|
||||
mutations; the public index exposes operations without the store. Notes deliberately
|
||||
retains last-completion fetch ordering. Do not infer request-generation guards from
|
||||
its decomposition. Its page-owned reminders survive panel closure, and panel/editor
|
||||
listeners and observers have separate disposal scopes.
|
||||
|
||||
Document lifecycle scopes: page, authenticated user, session, mounted panel and
|
||||
editor/draft. Name owners of subscriptions, DOM listeners, timers, observers,
|
||||
pending requests and caches. Mounting must be idempotent; disposal releases the
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
# Notes reference decomposition
|
||||
|
||||
Implementation started: 2026-10-13. Final validation: 2026-10-14.
|
||||
Foundation: [PR #6701](https://github.com/odysseus-dev/odysseus/pull/6701),
|
||||
`1cc56cb9d78f3e2399d1d61155b71d771a17b85b`. Branch was safely updated via
|
||||
non-destructive fast-forward to latest official `upstream/dev` at
|
||||
`86b886c611338282af6d4a717246ea4e256f58df`, incorporating PRs #6704 and #6693.
|
||||
Neither changed a file in the Notes diff. The independent AGY audit returned
|
||||
CONDITIONAL PASS; all pre-publication corrective actions (issue template conformance,
|
||||
PR template conformance, visual evidence paths, and em-dash removal) have been completed.
|
||||
|
||||
The entire implementation belongs to one Notes PR. N0 through N6 are internal
|
||||
checkpoints, not separate branches, commits or PRs. The [validation receipts](notes-validation.md),
|
||||
[module inventory](notes-module-inventory.md) and [changed-file inventory](notes-changed-files.md)
|
||||
accompany this case study.
|
||||
|
||||
## Responsibility map and size
|
||||
|
||||
The original `static/js/notes.js` contained 5,471 lines. It mixed mutable Notes
|
||||
data, view preferences, selection, undo, CRUD, date calculations, reminders,
|
||||
browser persistence, editor autosave, rendering, canvas tools and window management.
|
||||
Its import evaluated storage preferences and scheduled reminder initialization.
|
||||
|
||||
| Original responsibility | Maintained owner |
|
||||
| --- | --- |
|
||||
| Completion, tags, recurrence, date labels and serialization | `domain/recurrence.js`, `domain/noteRules.js` |
|
||||
| Notes data and selection/filter/editing state | `application/state.js`, instantiated once in `index.js` |
|
||||
| CRUD, undo and fetch completion ordering | `application/workflows.js`, `cardOperations.js`, `deletion.js` |
|
||||
| Checklist mutations and rollback | `application/checklistOperations.js` |
|
||||
| Editor optimistic submission and recovery | `application/submission.js` |
|
||||
| Serialized autosave and synchronous backup | `application/drafts.js`; form collection in `ui/draftEditor.js` |
|
||||
| Filtering, searching and ordering | `application/queries.js`; controls in `ui/filters.js` and `toolbar.js` |
|
||||
| Selected-note attachment and bulk requests | `application/selection.js`; controls in `ui/selection.js` |
|
||||
| Existing agent-solve workflow | `application/agentActions.js`, through supplied HTTP/session ports |
|
||||
| HTTP, persistence and browser notifications | `infrastructure/http.js`, `storage.js`, `notifications.js` |
|
||||
| Background scheduler and delivery decisions | `application/reminders.js` |
|
||||
| Panel mounting, closing, keyboard handling and navigation | `ui/panel.js` |
|
||||
| Docking, fullscreen bounds and stacking | `ui/windowLayout.js`, using existing shared capabilities |
|
||||
| Cards, card gestures, quick add and masonry | `ui/cardRendering.js`, `cardInteractions.js`, `cardChecklist.js`, `cardReorder.js`, `quickAdd.js`, `layout.js` |
|
||||
| Editor types, colors, reminders and checklists | `ui/editor.js`, `colors.js`, `reminderPicker.js`, `checklist.js` |
|
||||
| Drawing, local drawing undo and PNG upload | `ui/drawing.js` |
|
||||
| Mobile reader/editor and reorder gestures | `ui/mobileEditor.js`, `mobileReorder.js`, `checklistReorder.js` |
|
||||
| Clipboard, safe rendering and reminder display | `ui/clipboard.js`, `text.js`, `reminderDisplay.js` |
|
||||
| Owned document/window listener disposal | `ui/lifecycle.js`, with panel and observer disposal callbacks |
|
||||
| Composition and supported exports | `index.js`; five-line legacy facade at `static/js/notes.js` |
|
||||
|
||||
The feature has 41 maintained modules: two domain, eleven application, three
|
||||
infrastructure, twenty-four UI and one index. Source is counted once, excluding
|
||||
byte-identical deployment copies. Domain has 356 lines, application 826,
|
||||
infrastructure 112, UI 4,628, and composition 518: 6,440 maintained feature lines.
|
||||
The module inventory records final per-file counts. The legacy entry shrank
|
||||
from 5,471 to five lines. Interfaces and explicit composition increase the total
|
||||
source size; reducing total lines was not the architectural objective.
|
||||
|
||||
One 28-line stateless confetti renderer also moved to `shared/ui/confetti.js`.
|
||||
Notes and Compare both use it. Compare retains its existing `spawnConfetti` export,
|
||||
which is the same function as the shared export. This removes Notes' import of
|
||||
Compare's private voting implementation without migrating Compare itself.
|
||||
|
||||
## Dependency graph and composition
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Legacy[Legacy Notes URL and window bridge] --> Index[Notes index: one composition]
|
||||
Index --> UI[Notes UI factories]
|
||||
Index --> App[Application workflows and state owner]
|
||||
Index --> Ports[HTTP, persistence and notification adapters]
|
||||
UI --> Rules[Pure domain rules]
|
||||
App --> Rules
|
||||
Index --> Shared[Existing shared UI capabilities and maintained confetti]
|
||||
```
|
||||
|
||||
Application modules receive adapters and feedback operations as arguments. They
|
||||
do not import browser infrastructure or DOM views. Pure domain modules receive
|
||||
the clock at the original read sites. UI consumes a read-only state view and
|
||||
application operations. Composition supplies callbacks between views and workflows;
|
||||
modules do not import the coordinator back. F1 rejects maintained-source cycles.
|
||||
|
||||
There are nine exact legacy-import exceptions, all on the Notes index. They bridge
|
||||
the existing UI, modal, color-picker, drag, tile, dock, stacking, Escape and tour-hint
|
||||
capabilities at their existing URLs. Their removal condition is migration of the
|
||||
corresponding shared responsibility to maintained source with its identity and
|
||||
lifecycle contract verified. No new feature imports another feature's private internals.
|
||||
|
||||
## State and asynchronous ownership
|
||||
|
||||
`createNotesState` is called once. It owns the Notes collection, selection IDs,
|
||||
editing ID, search, filters, archive/view flags, loading and dismissed-reminder time.
|
||||
Neither the facade nor reminders create a second collection. The public feature API
|
||||
does not expose this store.
|
||||
|
||||
Internal views are read-only live views rather than detached snapshots. This choice
|
||||
preserves captured note identity: an existing asynchronous rollback still acts on
|
||||
the same captured note. Array/object writes and selection mutations must use the
|
||||
state owner's operations. Workflow-local undo queues and serialized draft promises,
|
||||
and UI-local canvas undo/gesture state, are not competing Notes stores.
|
||||
|
||||
Fetches retain the original last-completion behavior. An earlier request that
|
||||
finishes later can overwrite a later request's result. Tests pin this behavior;
|
||||
generation guards would be a separate behavioral change. Submission also retains
|
||||
the original first-temporary-note replacement rule. Multiple simultaneous creations
|
||||
need a separately reviewed correlation fix, not a silent change during extraction.
|
||||
|
||||
Archive, unarchive, pin, item edit/remove/add, delete and undo preserve their original
|
||||
optimistic ordering and rollback. Animation callbacks remain view-owned. Drawing
|
||||
save keeps the existing button guard around its asynchronous PNG upload. Draft writes
|
||||
are serialized per editor; a completed older save cannot clear a newer local draft.
|
||||
|
||||
Reminder scans still use the originally loaded Notes collection, not a second
|
||||
all-active cache. An archived-only collection or a failure-cleared list can defer
|
||||
active reminders until an active refresh/reopen. The timer remains alive when the
|
||||
panel closes, but extraction does not redesign this inherited data-availability
|
||||
limitation. Review such a change separately from scheduler/state ownership.
|
||||
|
||||
## Public compatibility
|
||||
|
||||
The import URL remains `/static/js/notes.js?v=20260911notesselectioncancel1`.
|
||||
App, Chat stream updates, Chat note links and Documents continue using their existing
|
||||
imports. Calendar and Documents retain their window bridge calls. HTML and app
|
||||
bootstrap code are unchanged. The service worker retains the exact legacy entry.
|
||||
|
||||
The legacy namespace still exports `openPanel`, `closePanel`, `togglePanel`,
|
||||
`isPanelOpen`, `openNote`, `newNote`, `refreshDueBadge`, `dismissFiredReminderDot`,
|
||||
`openNotes`, `closeNotes`, `isNotesOpen`, and `default`.
|
||||
The default object's ten methods are unchanged; `dismissFiredReminderDot` remains
|
||||
named-only. Aliases refer to the same functions, including those on the default
|
||||
object. `openNote` and `refreshDueBadge` remain async; function arities are pinned.
|
||||
|
||||
`window.notesModule` is exactly the default controller. The canonical unversioned
|
||||
feature index and both tested legacy entry URLs share the same controller and
|
||||
operations. The default object retains its existing mutability. A different legacy
|
||||
URL has its own ESM namespace, as native ESM requires, but creates no second store
|
||||
or scheduler because it forwards to the same canonical index.
|
||||
|
||||
The canonical index additionally exports `startNotesBackground` for explicit
|
||||
activation. The compatibility facade invokes it once through an idempotent start
|
||||
operation. Existing consumers need no change. Remove the facade only after every
|
||||
consumer, global bridge, bootstrap and offline reference has migrated together.
|
||||
|
||||
## Protected selected Notes/Todos integration
|
||||
|
||||
The sender dispatches `odysseus:notes-context-selected` on `window` with
|
||||
`{ noteIds, accepted: false }`. Dispatch and acknowledgement remain synchronous.
|
||||
Chat owns acceptance, its session/pending selection, the context indicator and
|
||||
the `selected_note_ids` send payload. Notes exits selection only after acceptance.
|
||||
Rejected selections stay selected and display the existing feedback.
|
||||
|
||||
No Chat internals were imported or changed. Existing session lifecycle events still
|
||||
transfer a pending selection on materialization, restore selections on chat switches,
|
||||
and reset them for a new chat. Backend ID validation and owner filtering remain
|
||||
authoritative. Unit/backend tests cover these contracts; the real authenticated
|
||||
browser probe verifies rejection, pending-chat acceptance, the actual indicator and
|
||||
new-chat reset. Live model execution is not part of that probe.
|
||||
|
||||
## Persistence and HTTP contracts
|
||||
|
||||
| Key | Preserved format |
|
||||
| --- | --- |
|
||||
| `odysseus-notes-view` | `list` or `grid` |
|
||||
| `odysseus-notes-labels-collapsed` | `1` or `0` |
|
||||
| `odysseus-notes-first-open-hint-v1` | Existing first-open marker |
|
||||
| `odysseus-notes-reminder-fired` | JSON array of IDs |
|
||||
| `odysseus-notes-reminder-glowed` | JSON array of IDs |
|
||||
| `odysseus-notes-reminder-pending-highlight` | JSON array of IDs |
|
||||
| `odysseus-notes-reminder-active-highlight` | JSON array of IDs |
|
||||
| `odysseus-notes-reminder-dismissed-at` | Decimal millisecond timestamp |
|
||||
| `odysseus-note-draft-<id>` and `odysseus-note-draft-__new__` | Existing JSON draft fields and `_ts` |
|
||||
|
||||
CRUD, reorder, upload, reminder firing, default-chat lookup, session creation and
|
||||
chat-stream requests keep their URLs, methods, credentials, payloads and error
|
||||
interpretation. Uploads retain `files` and optional `gallery_id` multipart fields.
|
||||
The agent-solve stream still disables `manage_notes` and drains without switching
|
||||
the user's chat. No backend implementation changed.
|
||||
|
||||
Storage backup failures still warn once; failed network saves keep recoverable
|
||||
drafts, including intentionally empty text. Draft JSON does not serialize a canvas
|
||||
bitmap. A drawing remains ephemeral until its explicit PNG upload, as before.
|
||||
|
||||
## Lifecycle scopes and explicit corrections
|
||||
|
||||
| Scope | Owner and disposal |
|
||||
| --- | --- |
|
||||
| Browser page | One reminder startup timeout and interval; page termination ends them. The reminder factory also has explicit disposal. |
|
||||
| Open panel | Capture/bubble keyboard handlers, reorder listeners and masonry observer; both close paths dispose them. |
|
||||
| Editor/canvas | Local DOM handlers and draft workflow; drawing's window listener is released when its canvas detaches or the panel closes. |
|
||||
| Mobile editor/gesture | Overlay and document touch handlers; owner replacement and panel disposal remove handlers and reset registration flags. |
|
||||
| Menus/hints | Notes portals close with the panel; shared dismiss functions unregister their Escape/tour lifetimes. |
|
||||
| File picker | Existing completion or 30-second cleanup owns the temporary input. |
|
||||
|
||||
Two implementation corrections follow the user's explicit lifecycle requirements.
|
||||
The original close paths canceled the supposedly background reminder interval.
|
||||
The new page-owned interval survives closing/minimizing Notes, while retaining the
|
||||
3-second startup delay, 30-second period and immediate first check. Closing a panel
|
||||
also releases owned observers/listeners, pending hold timers, active Notes gestures
|
||||
and portals; late panel fetch callbacks do
|
||||
not recreate UI on a detached panel. Network completion/state ordering is preserved.
|
||||
|
||||
Shared drag/window utilities continue owning their own active-gesture handlers.
|
||||
They were not moved into Notes. Idle open/close and editor replacement are verified;
|
||||
every possible interleaving with an active shared window drag was not tested.
|
||||
|
||||
## Source and deployment
|
||||
|
||||
Every maintained source is registered in `frontend/modules.json` and copied without
|
||||
rewriting imports. Notes sources map to `static/js/features/notes/` at the same
|
||||
relative paths. Shared confetti maps to `static/js/shared/ui/confetti.js`.
|
||||
Repository-owned LF attributes and byte parity cover all 43 maintained modules,
|
||||
including the unchanged F1 proof. The legacy facade is an authored compatibility
|
||||
entry, not a second implementation.
|
||||
|
||||
All new outputs join exact service-worker precache arrays. A real offline test also
|
||||
found eight previously missing exact legacy URLs in the Notes graph; those entries
|
||||
are now included. The eager Notes graph has 57 exact runtime URLs. Cache naming
|
||||
follows the repository's `odysseus-v659-notes-reference` convention. Root offline
|
||||
reload remains outside certification because the existing worker scope is `/static/`.
|
||||
|
||||
Python startup and Docker serve the committed static graph without maintained
|
||||
source or frontend tooling. The publisher is a development check/copy operation,
|
||||
not a runtime compiler or an atomic deployment system.
|
||||
|
||||
## Checkpoints, rollback and lessons
|
||||
|
||||
[Checkpoint receipts](notes-validation.md#internal-checkpoints) record the actual
|
||||
checks and local snapshot hashes. These intermediate snapshots are engineering
|
||||
evidence, not standalone release artifacts. N5 includes bounded editor, cards,
|
||||
checklist, drawing, mobile, toolbar and window reviews on the same branch.
|
||||
|
||||
The N3 mechanical state rewrite initially confused canvas-local and feature undo
|
||||
bindings. The N5 drawing test found it; the canvas binding was restored and the
|
||||
same drawing/undo interaction was replayed against the original implementation.
|
||||
Use scope-aware transformations and test each stateful UI responsibility before
|
||||
accepting a broad rewrite. Source parsing alone does not prove semantic equivalence.
|
||||
|
||||
For rollback, reconstruct the prior complete artifact from its revision/snapshot
|
||||
in a fresh temporary directory, run parity/graph/behavior checks there, then publish
|
||||
the matching static graph and service worker as a unit through the authorized
|
||||
release process. Restore the whole facade/source/output/manifest set, not just
|
||||
`notes.js`. No schema or storage-key migration needs reversal. Do not reset a dirty
|
||||
worktree or delete unrelated outputs. The validation report gives a non-destructive
|
||||
snapshot reproduction recipe.
|
||||
|
||||
For the next maintainer:
|
||||
|
||||
1. Start with the module inventory and the state/workflow contracts, then reproduce
|
||||
the focused tests, offline test and isolated native browser probe.
|
||||
2. Review the explicit timer/lifecycle corrections separately from unchanged
|
||||
business rules. Inspect both maintained source and byte-identical deployment.
|
||||
3. Resolve or track the reproduced upstream CI failures and the open PR overlaps
|
||||
before authorizing publication. Create/link the dedicated issue, then publish
|
||||
exactly one Notes PR targeting official `dev`.
|
||||
4. Record the integrated revision and independent recipient reproduction to complete
|
||||
H. The designated maintainer can then apply this method to future features.
|
||||
|
||||
For Calendar, Documents, Email and later monoliths, characterize actual exports,
|
||||
URL identities, state writers, clock reads, I/O and lifecycle first. Extract pure
|
||||
rules, then adapters, then a single state owner/workflows. Use explicit callback
|
||||
ports to break coordinator cycles. Split UI by interactions and resource lifetime,
|
||||
not by arbitrary line ranges. Transfer source/output ownership and offline URLs
|
||||
with each boundary, and preserve source-sensitive assertions at their new owner.
|
||||
Those feature migrations are not part of this implementation.
|
||||
@@ -0,0 +1,165 @@
|
||||
# Notes complete changed-file inventory
|
||||
|
||||
Changed files in PR #6713 (`refactor/notes-reference-decomposition`) against
|
||||
`dev`. 121 files: 16 modified and 105 added. No files are deleted. Deployment copies
|
||||
are byte-identical to their registered maintained sources. Image files are review
|
||||
evidence, not production dependencies.
|
||||
|
||||
The unchanged foundation worktree, backend, app bootstrap, HTML, CSS, dependency
|
||||
lockfiles, Dockerfile and CI workflow are outside this diff. The only Compare
|
||||
change delegates its existing stateless confetti export to maintained shared UI.
|
||||
|
||||
## Maintained source (42)
|
||||
|
||||
| Status | File |
|
||||
| --- | --- |
|
||||
| A | [frontend/src/features/notes/application/agentActions.js](../../frontend/src/features/notes/application/agentActions.js) |
|
||||
| A | [frontend/src/features/notes/application/cardOperations.js](../../frontend/src/features/notes/application/cardOperations.js) |
|
||||
| A | [frontend/src/features/notes/application/checklistOperations.js](../../frontend/src/features/notes/application/checklistOperations.js) |
|
||||
| A | [frontend/src/features/notes/application/deletion.js](../../frontend/src/features/notes/application/deletion.js) |
|
||||
| A | [frontend/src/features/notes/application/drafts.js](../../frontend/src/features/notes/application/drafts.js) |
|
||||
| A | [frontend/src/features/notes/application/queries.js](../../frontend/src/features/notes/application/queries.js) |
|
||||
| A | [frontend/src/features/notes/application/reminders.js](../../frontend/src/features/notes/application/reminders.js) |
|
||||
| A | [frontend/src/features/notes/application/selection.js](../../frontend/src/features/notes/application/selection.js) |
|
||||
| A | [frontend/src/features/notes/application/state.js](../../frontend/src/features/notes/application/state.js) |
|
||||
| A | [frontend/src/features/notes/application/submission.js](../../frontend/src/features/notes/application/submission.js) |
|
||||
| A | [frontend/src/features/notes/application/workflows.js](../../frontend/src/features/notes/application/workflows.js) |
|
||||
| A | [frontend/src/features/notes/domain/noteRules.js](../../frontend/src/features/notes/domain/noteRules.js) |
|
||||
| A | [frontend/src/features/notes/domain/recurrence.js](../../frontend/src/features/notes/domain/recurrence.js) |
|
||||
| A | [frontend/src/features/notes/index.js](../../frontend/src/features/notes/index.js) |
|
||||
| A | [frontend/src/features/notes/infrastructure/http.js](../../frontend/src/features/notes/infrastructure/http.js) |
|
||||
| A | [frontend/src/features/notes/infrastructure/notifications.js](../../frontend/src/features/notes/infrastructure/notifications.js) |
|
||||
| A | [frontend/src/features/notes/infrastructure/storage.js](../../frontend/src/features/notes/infrastructure/storage.js) |
|
||||
| A | [frontend/src/features/notes/ui/cardChecklist.js](../../frontend/src/features/notes/ui/cardChecklist.js) |
|
||||
| A | [frontend/src/features/notes/ui/cardInteractions.js](../../frontend/src/features/notes/ui/cardInteractions.js) |
|
||||
| A | [frontend/src/features/notes/ui/cardRendering.js](../../frontend/src/features/notes/ui/cardRendering.js) |
|
||||
| A | [frontend/src/features/notes/ui/cardReorder.js](../../frontend/src/features/notes/ui/cardReorder.js) |
|
||||
| A | [frontend/src/features/notes/ui/checklist.js](../../frontend/src/features/notes/ui/checklist.js) |
|
||||
| A | [frontend/src/features/notes/ui/checklistReorder.js](../../frontend/src/features/notes/ui/checklistReorder.js) |
|
||||
| A | [frontend/src/features/notes/ui/clipboard.js](../../frontend/src/features/notes/ui/clipboard.js) |
|
||||
| A | [frontend/src/features/notes/ui/colors.js](../../frontend/src/features/notes/ui/colors.js) |
|
||||
| A | [frontend/src/features/notes/ui/draftEditor.js](../../frontend/src/features/notes/ui/draftEditor.js) |
|
||||
| A | [frontend/src/features/notes/ui/drawing.js](../../frontend/src/features/notes/ui/drawing.js) |
|
||||
| A | [frontend/src/features/notes/ui/editor.js](../../frontend/src/features/notes/ui/editor.js) |
|
||||
| A | [frontend/src/features/notes/ui/filters.js](../../frontend/src/features/notes/ui/filters.js) |
|
||||
| A | [frontend/src/features/notes/ui/layout.js](../../frontend/src/features/notes/ui/layout.js) |
|
||||
| A | [frontend/src/features/notes/ui/lifecycle.js](../../frontend/src/features/notes/ui/lifecycle.js) |
|
||||
| A | [frontend/src/features/notes/ui/mobileEditor.js](../../frontend/src/features/notes/ui/mobileEditor.js) |
|
||||
| A | [frontend/src/features/notes/ui/mobileReorder.js](../../frontend/src/features/notes/ui/mobileReorder.js) |
|
||||
| A | [frontend/src/features/notes/ui/panel.js](../../frontend/src/features/notes/ui/panel.js) |
|
||||
| A | [frontend/src/features/notes/ui/quickAdd.js](../../frontend/src/features/notes/ui/quickAdd.js) |
|
||||
| A | [frontend/src/features/notes/ui/reminderDisplay.js](../../frontend/src/features/notes/ui/reminderDisplay.js) |
|
||||
| A | [frontend/src/features/notes/ui/reminderPicker.js](../../frontend/src/features/notes/ui/reminderPicker.js) |
|
||||
| A | [frontend/src/features/notes/ui/selection.js](../../frontend/src/features/notes/ui/selection.js) |
|
||||
| A | [frontend/src/features/notes/ui/text.js](../../frontend/src/features/notes/ui/text.js) |
|
||||
| A | [frontend/src/features/notes/ui/toolbar.js](../../frontend/src/features/notes/ui/toolbar.js) |
|
||||
| A | [frontend/src/features/notes/ui/windowLayout.js](../../frontend/src/features/notes/ui/windowLayout.js) |
|
||||
| A | [frontend/src/shared/ui/confetti.js](../../frontend/src/shared/ui/confetti.js) |
|
||||
|
||||
## Deployment copies (42)
|
||||
|
||||
| Status | File |
|
||||
| --- | --- |
|
||||
| A | [static/js/features/notes/application/agentActions.js](../../static/js/features/notes/application/agentActions.js) |
|
||||
| A | [static/js/features/notes/application/cardOperations.js](../../static/js/features/notes/application/cardOperations.js) |
|
||||
| A | [static/js/features/notes/application/checklistOperations.js](../../static/js/features/notes/application/checklistOperations.js) |
|
||||
| A | [static/js/features/notes/application/deletion.js](../../static/js/features/notes/application/deletion.js) |
|
||||
| A | [static/js/features/notes/application/drafts.js](../../static/js/features/notes/application/drafts.js) |
|
||||
| A | [static/js/features/notes/application/queries.js](../../static/js/features/notes/application/queries.js) |
|
||||
| A | [static/js/features/notes/application/reminders.js](../../static/js/features/notes/application/reminders.js) |
|
||||
| A | [static/js/features/notes/application/selection.js](../../static/js/features/notes/application/selection.js) |
|
||||
| A | [static/js/features/notes/application/state.js](../../static/js/features/notes/application/state.js) |
|
||||
| A | [static/js/features/notes/application/submission.js](../../static/js/features/notes/application/submission.js) |
|
||||
| A | [static/js/features/notes/application/workflows.js](../../static/js/features/notes/application/workflows.js) |
|
||||
| A | [static/js/features/notes/domain/noteRules.js](../../static/js/features/notes/domain/noteRules.js) |
|
||||
| A | [static/js/features/notes/domain/recurrence.js](../../static/js/features/notes/domain/recurrence.js) |
|
||||
| A | [static/js/features/notes/index.js](../../static/js/features/notes/index.js) |
|
||||
| A | [static/js/features/notes/infrastructure/http.js](../../static/js/features/notes/infrastructure/http.js) |
|
||||
| A | [static/js/features/notes/infrastructure/notifications.js](../../static/js/features/notes/infrastructure/notifications.js) |
|
||||
| A | [static/js/features/notes/infrastructure/storage.js](../../static/js/features/notes/infrastructure/storage.js) |
|
||||
| A | [static/js/features/notes/ui/cardChecklist.js](../../static/js/features/notes/ui/cardChecklist.js) |
|
||||
| A | [static/js/features/notes/ui/cardInteractions.js](../../static/js/features/notes/ui/cardInteractions.js) |
|
||||
| A | [static/js/features/notes/ui/cardRendering.js](../../static/js/features/notes/ui/cardRendering.js) |
|
||||
| A | [static/js/features/notes/ui/cardReorder.js](../../static/js/features/notes/ui/cardReorder.js) |
|
||||
| A | [static/js/features/notes/ui/checklist.js](../../static/js/features/notes/ui/checklist.js) |
|
||||
| A | [static/js/features/notes/ui/checklistReorder.js](../../static/js/features/notes/ui/checklistReorder.js) |
|
||||
| A | [static/js/features/notes/ui/clipboard.js](../../static/js/features/notes/ui/clipboard.js) |
|
||||
| A | [static/js/features/notes/ui/colors.js](../../static/js/features/notes/ui/colors.js) |
|
||||
| A | [static/js/features/notes/ui/draftEditor.js](../../static/js/features/notes/ui/draftEditor.js) |
|
||||
| A | [static/js/features/notes/ui/drawing.js](../../static/js/features/notes/ui/drawing.js) |
|
||||
| A | [static/js/features/notes/ui/editor.js](../../static/js/features/notes/ui/editor.js) |
|
||||
| A | [static/js/features/notes/ui/filters.js](../../static/js/features/notes/ui/filters.js) |
|
||||
| A | [static/js/features/notes/ui/layout.js](../../static/js/features/notes/ui/layout.js) |
|
||||
| A | [static/js/features/notes/ui/lifecycle.js](../../static/js/features/notes/ui/lifecycle.js) |
|
||||
| A | [static/js/features/notes/ui/mobileEditor.js](../../static/js/features/notes/ui/mobileEditor.js) |
|
||||
| A | [static/js/features/notes/ui/mobileReorder.js](../../static/js/features/notes/ui/mobileReorder.js) |
|
||||
| A | [static/js/features/notes/ui/panel.js](../../static/js/features/notes/ui/panel.js) |
|
||||
| A | [static/js/features/notes/ui/quickAdd.js](../../static/js/features/notes/ui/quickAdd.js) |
|
||||
| A | [static/js/features/notes/ui/reminderDisplay.js](../../static/js/features/notes/ui/reminderDisplay.js) |
|
||||
| A | [static/js/features/notes/ui/reminderPicker.js](../../static/js/features/notes/ui/reminderPicker.js) |
|
||||
| A | [static/js/features/notes/ui/selection.js](../../static/js/features/notes/ui/selection.js) |
|
||||
| A | [static/js/features/notes/ui/text.js](../../static/js/features/notes/ui/text.js) |
|
||||
| A | [static/js/features/notes/ui/toolbar.js](../../static/js/features/notes/ui/toolbar.js) |
|
||||
| A | [static/js/features/notes/ui/windowLayout.js](../../static/js/features/notes/ui/windowLayout.js) |
|
||||
| A | [static/js/shared/ui/confetti.js](../../static/js/shared/ui/confetti.js) |
|
||||
|
||||
## Compatibility and deployment configuration (5)
|
||||
|
||||
| Status | File |
|
||||
| --- | --- |
|
||||
| M | [.gitattributes](../../.gitattributes) |
|
||||
| M | [frontend/modules.json](../../frontend/modules.json) |
|
||||
| M | [static/js/compare/vote.js](../../static/js/compare/vote.js) |
|
||||
| M | [static/js/notes.js](../../static/js/notes.js) |
|
||||
| M | [static/sw.js](../../static/sw.js) |
|
||||
|
||||
## Tests (21)
|
||||
|
||||
| Status | File |
|
||||
| --- | --- |
|
||||
| A | [tests/browser/notesNative.mjs](../../tests/browser/notesNative.mjs) |
|
||||
| A | [tests/browser/notesOffline.mjs](../../tests/browser/notesOffline.mjs) |
|
||||
| A | [tests/browser/notesReference.mjs](../../tests/browser/notesReference.mjs) |
|
||||
| A | [tests/fixtures/notesRecurrenceBaseline.mjs](../../tests/fixtures/notesRecurrenceBaseline.mjs) |
|
||||
| A | [tests/helpers/notes_source.py](../../tests/helpers/notes_source.py) |
|
||||
| A | [tests/notesApplication.test.mjs](../../tests/notesApplication.test.mjs) |
|
||||
| A | [tests/notesCharacterization.test.mjs](../../tests/notesCharacterization.test.mjs) |
|
||||
| M | [tests/notesDraftAutosave.test.mjs](../../tests/notesDraftAutosave.test.mjs) |
|
||||
| A | [tests/notesInfrastructure.test.mjs](../../tests/notesInfrastructure.test.mjs) |
|
||||
| A | [tests/notesRecurrence.test.mjs](../../tests/notesRecurrence.test.mjs) |
|
||||
| A | [tests/notesReminders.test.mjs](../../tests/notesReminders.test.mjs) |
|
||||
| A | [tests/notesWorkflows.test.mjs](../../tests/notesWorkflows.test.mjs) |
|
||||
| M | [tests/selectedNotesContext.test.mjs](../../tests/selectedNotesContext.test.mjs) |
|
||||
| M | [tests/test_notes_document_mutual_minimize.py](../../tests/test_notes_document_mutual_minimize.py) |
|
||||
| M | [tests/test_notes_dom_xss_helpers.py](../../tests/test_notes_dom_xss_helpers.py) |
|
||||
| M | [tests/test_notes_mobile_checklist_toggle_static.py](../../tests/test_notes_mobile_checklist_toggle_static.py) |
|
||||
| A | [tests/test_notes_reference_browser.py](../../tests/test_notes_reference_browser.py) |
|
||||
| A | [tests/test_notes_reference_contracts_js.py](../../tests/test_notes_reference_contracts_js.py) |
|
||||
| M | [tests/test_notes_search_reset_on_reopen_js.py](../../tests/test_notes_search_reset_on_reopen_js.py) |
|
||||
| M | [tests/test_notes_select_esc_listener_js.py](../../tests/test_notes_select_esc_listener_js.py) |
|
||||
| M | [tests/test_notes_sidebar_new_note.py](../../tests/test_notes_sidebar_new_note.py) |
|
||||
|
||||
## Runtime validation (2)
|
||||
|
||||
| Status | File |
|
||||
| --- | --- |
|
||||
| M | [scripts/verify_frontend_runtime.py](../../scripts/verify_frontend_runtime.py) |
|
||||
| A | [scripts/verify_notes_browser_runtime.py](../../scripts/verify_notes_browser_runtime.py) |
|
||||
|
||||
## Documentation and execution receipts (9)
|
||||
|
||||
| Status | File |
|
||||
| --- | --- |
|
||||
| A | [docs/frontend-architecture/evidence/notes/implementation.sha256](../../docs/frontend-architecture/evidence/notes/implementation.sha256) |
|
||||
| A | [docs/frontend-architecture/evidence/notes/native-desktop.png](../../docs/frontend-architecture/evidence/notes/native-desktop.png) |
|
||||
| A | [docs/frontend-architecture/evidence/notes/native-mobile.png](../../docs/frontend-architecture/evidence/notes/native-mobile.png) |
|
||||
| M | [docs/frontend-architecture/handbook.md](../../docs/frontend-architecture/handbook.md) |
|
||||
| A | [docs/frontend-architecture/notes-case-study.md](../../docs/frontend-architecture/notes-case-study.md) |
|
||||
| A | [docs/frontend-architecture/notes-changed-files.md](../../docs/frontend-architecture/notes-changed-files.md) |
|
||||
| A | [docs/frontend-architecture/notes-module-inventory.md](../../docs/frontend-architecture/notes-module-inventory.md) |
|
||||
| M | [docs/frontend-architecture/notes-roadmap.md](../../docs/frontend-architecture/notes-roadmap.md) |
|
||||
| A | [docs/frontend-architecture/notes-validation.md](../../docs/frontend-architecture/notes-validation.md) |
|
||||
|
||||
See [the case study](notes-case-study.md) for ownership and handoff,
|
||||
[the module inventory](notes-module-inventory.md) for line counts, and
|
||||
[the validation report](notes-validation.md) for exact executed checks.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Notes source and deployment inventory
|
||||
|
||||
The feature has 41 maintained modules. The unchanged F1 action-menu proof and
|
||||
shared confetti bring the full manifest to 43. Outputs are copied byte-for-byte;
|
||||
count maintained source once. The legacy entry is a five-line compatibility facade.
|
||||
|
||||
| Source under frontend/src | Deployment under static | Lines | Layer |
|
||||
| --- | --- | ---: | --- |
|
||||
| [features/notes/application/agentActions.js](../../frontend/src/features/notes/application/agentActions.js) | [js/features/notes/application/agentActions.js](../../static/js/features/notes/application/agentActions.js) | 67 | application |
|
||||
| [features/notes/application/cardOperations.js](../../frontend/src/features/notes/application/cardOperations.js) | [js/features/notes/application/cardOperations.js](../../static/js/features/notes/application/cardOperations.js) | 79 | application |
|
||||
| [features/notes/application/checklistOperations.js](../../frontend/src/features/notes/application/checklistOperations.js) | [js/features/notes/application/checklistOperations.js](../../static/js/features/notes/application/checklistOperations.js) | 68 | application |
|
||||
| [features/notes/application/deletion.js](../../frontend/src/features/notes/application/deletion.js) | [js/features/notes/application/deletion.js](../../static/js/features/notes/application/deletion.js) | 51 | application |
|
||||
| [features/notes/application/drafts.js](../../frontend/src/features/notes/application/drafts.js) | [js/features/notes/application/drafts.js](../../static/js/features/notes/application/drafts.js) | 55 | application |
|
||||
| [features/notes/application/queries.js](../../frontend/src/features/notes/application/queries.js) | [js/features/notes/application/queries.js](../../static/js/features/notes/application/queries.js) | 66 | application |
|
||||
| [features/notes/application/reminders.js](../../frontend/src/features/notes/application/reminders.js) | [js/features/notes/application/reminders.js](../../static/js/features/notes/application/reminders.js) | 182 | application |
|
||||
| [features/notes/application/selection.js](../../frontend/src/features/notes/application/selection.js) | [js/features/notes/application/selection.js](../../static/js/features/notes/application/selection.js) | 39 | application |
|
||||
| [features/notes/application/state.js](../../frontend/src/features/notes/application/state.js) | [js/features/notes/application/state.js](../../static/js/features/notes/application/state.js) | 72 | application |
|
||||
| [features/notes/application/submission.js](../../frontend/src/features/notes/application/submission.js) | [js/features/notes/application/submission.js](../../static/js/features/notes/application/submission.js) | 69 | application |
|
||||
| [features/notes/application/workflows.js](../../frontend/src/features/notes/application/workflows.js) | [js/features/notes/application/workflows.js](../../static/js/features/notes/application/workflows.js) | 78 | application |
|
||||
| [features/notes/domain/noteRules.js](../../frontend/src/features/notes/domain/noteRules.js) | [js/features/notes/domain/noteRules.js](../../static/js/features/notes/domain/noteRules.js) | 87 | domain |
|
||||
| [features/notes/domain/recurrence.js](../../frontend/src/features/notes/domain/recurrence.js) | [js/features/notes/domain/recurrence.js](../../static/js/features/notes/domain/recurrence.js) | 269 | domain |
|
||||
| [features/notes/index.js](../../frontend/src/features/notes/index.js) | [js/features/notes/index.js](../../static/js/features/notes/index.js) | 518 | composition |
|
||||
| [features/notes/infrastructure/http.js](../../frontend/src/features/notes/infrastructure/http.js) | [js/features/notes/infrastructure/http.js](../../static/js/features/notes/infrastructure/http.js) | 29 | infrastructure |
|
||||
| [features/notes/infrastructure/notifications.js](../../frontend/src/features/notes/infrastructure/notifications.js) | [js/features/notes/infrastructure/notifications.js](../../static/js/features/notes/infrastructure/notifications.js) | 20 | infrastructure |
|
||||
| [features/notes/infrastructure/storage.js](../../frontend/src/features/notes/infrastructure/storage.js) | [js/features/notes/infrastructure/storage.js](../../static/js/features/notes/infrastructure/storage.js) | 63 | infrastructure |
|
||||
| [features/notes/ui/cardChecklist.js](../../frontend/src/features/notes/ui/cardChecklist.js) | [js/features/notes/ui/cardChecklist.js](../../static/js/features/notes/ui/cardChecklist.js) | 148 | ui |
|
||||
| [features/notes/ui/cardInteractions.js](../../frontend/src/features/notes/ui/cardInteractions.js) | [js/features/notes/ui/cardInteractions.js](../../static/js/features/notes/ui/cardInteractions.js) | 337 | ui |
|
||||
| [features/notes/ui/cardRendering.js](../../frontend/src/features/notes/ui/cardRendering.js) | [js/features/notes/ui/cardRendering.js](../../static/js/features/notes/ui/cardRendering.js) | 244 | ui |
|
||||
| [features/notes/ui/cardReorder.js](../../frontend/src/features/notes/ui/cardReorder.js) | [js/features/notes/ui/cardReorder.js](../../static/js/features/notes/ui/cardReorder.js) | 181 | ui |
|
||||
| [features/notes/ui/checklist.js](../../frontend/src/features/notes/ui/checklist.js) | [js/features/notes/ui/checklist.js](../../static/js/features/notes/ui/checklist.js) | 190 | ui |
|
||||
| [features/notes/ui/checklistReorder.js](../../frontend/src/features/notes/ui/checklistReorder.js) | [js/features/notes/ui/checklistReorder.js](../../static/js/features/notes/ui/checklistReorder.js) | 111 | ui |
|
||||
| [features/notes/ui/clipboard.js](../../frontend/src/features/notes/ui/clipboard.js) | [js/features/notes/ui/clipboard.js](../../static/js/features/notes/ui/clipboard.js) | 82 | ui |
|
||||
| [features/notes/ui/colors.js](../../frontend/src/features/notes/ui/colors.js) | [js/features/notes/ui/colors.js](../../static/js/features/notes/ui/colors.js) | 111 | ui |
|
||||
| [features/notes/ui/draftEditor.js](../../frontend/src/features/notes/ui/draftEditor.js) | [js/features/notes/ui/draftEditor.js](../../static/js/features/notes/ui/draftEditor.js) | 67 | ui |
|
||||
| [features/notes/ui/drawing.js](../../frontend/src/features/notes/ui/drawing.js) | [js/features/notes/ui/drawing.js](../../static/js/features/notes/ui/drawing.js) | 442 | ui |
|
||||
| [features/notes/ui/editor.js](../../frontend/src/features/notes/ui/editor.js) | [js/features/notes/ui/editor.js](../../static/js/features/notes/ui/editor.js) | 518 | ui |
|
||||
| [features/notes/ui/filters.js](../../frontend/src/features/notes/ui/filters.js) | [js/features/notes/ui/filters.js](../../static/js/features/notes/ui/filters.js) | 139 | ui |
|
||||
| [features/notes/ui/layout.js](../../frontend/src/features/notes/ui/layout.js) | [js/features/notes/ui/layout.js](../../static/js/features/notes/ui/layout.js) | 120 | ui |
|
||||
| [features/notes/ui/lifecycle.js](../../frontend/src/features/notes/ui/lifecycle.js) | [js/features/notes/ui/lifecycle.js](../../static/js/features/notes/ui/lifecycle.js) | 36 | ui |
|
||||
| [features/notes/ui/mobileEditor.js](../../frontend/src/features/notes/ui/mobileEditor.js) | [js/features/notes/ui/mobileEditor.js](../../static/js/features/notes/ui/mobileEditor.js) | 257 | ui |
|
||||
| [features/notes/ui/mobileReorder.js](../../frontend/src/features/notes/ui/mobileReorder.js) | [js/features/notes/ui/mobileReorder.js](../../static/js/features/notes/ui/mobileReorder.js) | 214 | ui |
|
||||
| [features/notes/ui/panel.js](../../frontend/src/features/notes/ui/panel.js) | [js/features/notes/ui/panel.js](../../static/js/features/notes/ui/panel.js) | 506 | ui |
|
||||
| [features/notes/ui/quickAdd.js](../../frontend/src/features/notes/ui/quickAdd.js) | [js/features/notes/ui/quickAdd.js](../../static/js/features/notes/ui/quickAdd.js) | 170 | ui |
|
||||
| [features/notes/ui/reminderDisplay.js](../../frontend/src/features/notes/ui/reminderDisplay.js) | [js/features/notes/ui/reminderDisplay.js](../../static/js/features/notes/ui/reminderDisplay.js) | 129 | ui |
|
||||
| [features/notes/ui/reminderPicker.js](../../frontend/src/features/notes/ui/reminderPicker.js) | [js/features/notes/ui/reminderPicker.js](../../static/js/features/notes/ui/reminderPicker.js) | 334 | ui |
|
||||
| [features/notes/ui/selection.js](../../frontend/src/features/notes/ui/selection.js) | [js/features/notes/ui/selection.js](../../static/js/features/notes/ui/selection.js) | 61 | ui |
|
||||
| [features/notes/ui/text.js](../../frontend/src/features/notes/ui/text.js) | [js/features/notes/ui/text.js](../../static/js/features/notes/ui/text.js) | 39 | ui |
|
||||
| [features/notes/ui/toolbar.js](../../frontend/src/features/notes/ui/toolbar.js) | [js/features/notes/ui/toolbar.js](../../static/js/features/notes/ui/toolbar.js) | 78 | ui |
|
||||
| [features/notes/ui/windowLayout.js](../../frontend/src/features/notes/ui/windowLayout.js) | [js/features/notes/ui/windowLayout.js](../../static/js/features/notes/ui/windowLayout.js) | 114 | ui |
|
||||
| [shared/ui/confetti.js](../../frontend/src/shared/ui/confetti.js) | [js/shared/ui/confetti.js](../../static/js/shared/ui/confetti.js) | 28 | shared UI |
|
||||
|
||||
Maintained Notes feature total: 6440 lines. Original entry: 5,471 lines.
|
||||
Legacy facade after decomposition: five lines. Shared confetti: 28 lines.
|
||||
|
||||
See [the case study](notes-case-study.md) for responsibilities and public/state/lifecycle
|
||||
contracts, and [the validation report](notes-validation.md) for executed evidence.
|
||||
@@ -1,15 +1,20 @@
|
||||
# Notes reference decomposition roadmap
|
||||
|
||||
Status: planning only. F1 changes no Notes implementation. Begin after the
|
||||
foundation has been reviewed and integrated into official `upstream/dev`.
|
||||
The reference program ends after Notes integration and the completed H handoff.
|
||||
Status: N0 through N6 implemented as an unpublished Notes review diff after F1
|
||||
merged in PR #6701. Actual decisions, interfaces, module ownership, checkpoint
|
||||
receipts and execution limits are in the [case study](notes-case-study.md) and
|
||||
[validation report](notes-validation.md). The proposal below retains the original
|
||||
responsibility map for comparison. Notes integration and the recipient's independent
|
||||
H reproduction remain pending.
|
||||
F1 remains an entirely separate foundation-only PR. The complete Notes
|
||||
decomposition, regression tests, compatibility validation and final reference
|
||||
case study belong to one comprehensive draft PR targeting official `dev`.
|
||||
|
||||
## Verified current responsibility and compatibility map
|
||||
|
||||
Baseline: `8feb50e89468235cd3e0986da80edbd3acaf2c40`.
|
||||
Historical assessment baseline: `8feb50e89468235cd3e0986da80edbd3acaf2c40`.
|
||||
The implementation starts from merged F1 at
|
||||
`1cc56cb9d78f3e2399d1d61155b71d771a17b85b`.
|
||||
The module is `static/js/notes.js`, about 5,470 lines, with browser identity
|
||||
`/static/js/notes.js?v=20260911notesselectioncancel1`. Preserve that identity across
|
||||
the app import, HTML, SW and lazy consumers until a separately reviewed migration
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
# Notes implementation validation and checkpoint receipts
|
||||
|
||||
Implementation baseline: `1cc56cb9d78f3e2399d1d61155b71d771a17b85b`, updated via
|
||||
non-destructive fast-forward to latest official `upstream/dev` at
|
||||
`86b886c611338282af6d4a717246ea4e256f58df` (incorporating PRs #6704 and #6693).
|
||||
Independent AGY audit returned CONDITIONAL PASS. Pre-publication corrective
|
||||
pass verified issue template, PR template, visual evidence paths, and em-dash removal.
|
||||
The official integration branch is `dev`. Tracking issue #6712; PR #6713.
|
||||
|
||||
## Final executed evidence
|
||||
|
||||
| Check | Result |
|
||||
| --- | --- |
|
||||
| Notes Python tests, discovered by filename, plus F1 publication/graph/offline/loader tests | 172 passed, one release-smoke skip without `APP_PORT` |
|
||||
| Node architecture, Notes oracle, domain, infrastructure, application, reminders, drafts, selection and workflow tests | 46 passed |
|
||||
| Native Python lifespan/static distribution probe | Passed for every mapped output, with source/Node absent |
|
||||
| Existing Docker image distribution probe | Passed with networking disabled and candidate files mounted read-only |
|
||||
| Real authenticated native app, desktop and touch-mobile | Passed CRUD persistence, owner identity, actual Chat selected-context indicator/reset and the original release smoke scenario |
|
||||
| Real Chromium first evaluation of Notes offline | Passed; every maintained output cached, facade/canonical API identity shared |
|
||||
| Source/output parity and F1 boundaries | Passed, 43 maintained modules and nine composition-only legacy exceptions |
|
||||
| Foundation-based full pytest execution | 13 failed, 13,909 passed, 60 skipped, six subtests passed, 192 warnings, 517.04 seconds |
|
||||
| Targeted unchanged F1 baseline reproduction | Same 13 failures, 77 passed, six warnings |
|
||||
| Targeted untouched latest `dev` reproduction | Three inherited failures, 87 passed, six warnings |
|
||||
| Final indexed latest `dev` plus Notes overlay, full pytest | Three same-environment baseline failures, 13,923 passed, 60 skipped, six subtests passed, 192 warnings, 512.09 seconds |
|
||||
| Untouched latest `dev` readiness checks, without the prewarm override | Five passed |
|
||||
|
||||
The foundation-based full repository result is not green. Its failures reproduce against
|
||||
the unchanged foundation in a disposable archive, with the same interpreter and
|
||||
closed Chroma port. None was disabled, relabeled or fixed in this Notes change.
|
||||
The focused Notes suite and required source/deployment gates are green. The final
|
||||
code/test overlay is fingerprinted in [implementation.sha256](evidence/notes/implementation.sha256).
|
||||
The only post-full-suite test-source edit removes a terminal
|
||||
blank line from the browser wrapper; its content was compared ignoring terminal
|
||||
whitespace and all three focused contract/browser checks passed again. Raw command
|
||||
outputs are kept out of the repository; the counts above are the record.
|
||||
|
||||
The first full run reported 19 failures. Six were introduced validation issues:
|
||||
the SW cache name did not follow the existing numeric convention; a temporary
|
||||
probe environment input was not registered by the configuration-reference checker;
|
||||
and a Notes source assertion still expected the original default object spelling.
|
||||
The cache name now follows the convention, the probe passes its output list as a
|
||||
command argument, and the assertion verifies the new public binding. All 58 tests
|
||||
in those affected files passed after correction. The foundation-based full run has only the
|
||||
13 reproduced baseline failures below.
|
||||
|
||||
### Reproduced baseline failures
|
||||
|
||||
- `tests/test_aux_llm_owner_scope.py::test_auto_compaction_utility_endpoint_keeps_chat_owner`
|
||||
- `tests/test_chatgpt_reasoning_and_grouping.py::test_history_and_chat_routes_support_reasoning_effort`
|
||||
- `tests/test_containment_enforcement.py::test_namespace_handshake_closes_model_stdin`
|
||||
- `tests/test_containment_enforcement.py::test_execution_environment_cannot_replace_probed_bwrap[False]`
|
||||
- `tests/test_context_compactor.py::TestMaybeCompactFourthMessage::test_does_not_crash_on_none_content_turn`
|
||||
- `tests/test_context_compactor.py::TestMaybeCompactFourthMessage::test_handles_multimodal_list_content`
|
||||
- `tests/test_css_computed_style_snapshot.py::test_computed_styles_match_the_committed_baseline`
|
||||
- `tests/test_history_compact_tool_calls.py::test_manual_compact_tolerates_chatmessage_with_none_content`
|
||||
- `tests/test_history_compact_tool_calls.py::test_manual_compact_tolerates_dict_message_with_none_content`
|
||||
- `tests/test_history_compact_tool_calls.py::test_registered_manual_compact_route_tolerates_none_content`
|
||||
- `tests/test_history_compact_tool_calls.py::test_registered_manual_compact_route_uses_session_owner`
|
||||
- `tests/test_model_helper_owner_scope.py::test_history_compact_resolves_with_owner_scope`
|
||||
- `tests/test_readiness.py::test_tool_index_is_reported_but_not_critical_by_default`
|
||||
|
||||
These cover existing compaction fixtures/source assertions, namespace containment,
|
||||
settings-row CSS baseline drift and readiness expectations. The baseline reproduction used
|
||||
`git archive` into `/tmp/odysseus-notes-baseline-OitxsU`, not another branch/worktree.
|
||||
|
||||
## Reproducible commands
|
||||
|
||||
### Latest integration target
|
||||
|
||||
Final upstream inspection found `86b886c611338282af6d4a717246ea4e256f58df`.
|
||||
PR #6704 repairs ten of the foundation's reproduced failures; PR #6693 adds
|
||||
remote-only skill gating. Neither changes a file owned by the Notes diff.
|
||||
The branch remains on the requested foundation, with no merge or rebase.
|
||||
An archive of that latest target plus the exact final Notes code/test overlay is
|
||||
validated in `/tmp/odysseus-notes-latest-VmZrgC` using the same full-suite command.
|
||||
The fixture has a local Git index, initialized from the latest target and updated
|
||||
with the review files, but no commit. This enables the tracked-publication checks.
|
||||
The first archive-only attempt had one Git-metadata failure and seven checkout-only
|
||||
skips. Both affected files subsequently passed all 19 tests with metadata present;
|
||||
the complete suite was then rerun in that indexed fixture.
|
||||
An untouched archive at `/tmp/odysseus-notes-latest-baseline-mfE4ss` reproduced
|
||||
the remaining two containment failures and the readiness failure: three failed,
|
||||
87 passed.
|
||||
|
||||
These are reproduced local-environment failures, not a claim that official CI is
|
||||
currently failing. The readiness assertion expects prewarming enabled, whereas
|
||||
the full-run safety command explicitly sets `ODYSSEUS_TOOL_INDEX_PREWARM=0`.
|
||||
With that override absent, all five readiness tests pass on untouched latest `dev`.
|
||||
The two namespace tests receive extra `Failed to create stream fd` stderr in this
|
||||
host's contained process output. That same output occurs without the Notes overlay;
|
||||
no backend containment code was changed or a failing assertion weakened.
|
||||
Reproduce those two checks on the supported CI runner before claiming a green
|
||||
full-suite certification.
|
||||
|
||||
In the final indexed full-suite run the only failures are `test_namespace_handshake_closes_model_stdin`,
|
||||
`test_execution_environment_cannot_replace_probed_bwrap[False]`, and
|
||||
`test_tool_index_is_reported_but_not_critical_by_default`. The missing-Git-metadata
|
||||
publication failure and the seven checkout-only skips are absent from this run.
|
||||
No Notes regression was reported. Feature code matched N6 at publication. Later
|
||||
commits on the PR changed `ui/reminderPicker.js` (date input value assigned through
|
||||
the DOM property) and, after review, `index.js`, `ui/layout.js` and
|
||||
`application/state.js`; `implementation.sha256` covers the current files.
|
||||
|
||||
To reproduce the integration rehearsal, extract the latest target with `git archive`
|
||||
into a fresh fixture and copy only files in the changed-file inventory on top.
|
||||
Do not overlay foundation files that are unchanged in this PR. Install the locked
|
||||
development dependencies in the fixture, then run the commands below there.
|
||||
|
||||
While this review diff is uncommitted, this prepares an equivalent Linux fixture
|
||||
without changing either task worktree:
|
||||
|
||||
```sh
|
||||
notes_fixture=$(mktemp -d /tmp/ody-notes-integration-XXXXXX)
|
||||
git archive 86b886c611338282af6d4a717246ea4e256f58df | tar -x -C "$notes_fixture"
|
||||
{ git diff --name-only -z; git ls-files --others --exclude-standard -z; } |
|
||||
tar --null -T - -cf - | tar -xf - -C "$notes_fixture"
|
||||
git -C "$notes_fixture" init -q
|
||||
git -C "$notes_fixture" fetch --no-write-fetch-head "$PWD" 86b886c611338282af6d4a717246ea4e256f58df
|
||||
git -C "$notes_fixture" read-tree 86b886c611338282af6d4a717246ea4e256f58df
|
||||
(cd "$notes_fixture" && npm ci --ignore-scripts --no-audit --no-fund && git add --all)
|
||||
# Run the validation commands below from notes_fixture, using an isolated Python environment.
|
||||
```
|
||||
|
||||
Use a real dependency directory for this recipe; a symlink named `node_modules`
|
||||
can bypass the repository's directory-only ignore pattern. No checkpoint or
|
||||
fixture commit is needed. After integration, validate the actual integrated checkout
|
||||
directly, rather than relying on the uncommitted-diff recipe.
|
||||
|
||||
### Commands
|
||||
|
||||
Use the actual tested interpreter, or install the repository requirements in your
|
||||
own isolated virtualenv. Node development dependencies were installed with the
|
||||
existing lockfile and `npm ci --ignore-scripts --no-audit --no-fund`.
|
||||
|
||||
```sh
|
||||
python3 scripts/build_frontend.py
|
||||
python3 scripts/build_frontend.py --check
|
||||
node scripts/check_frontend.mjs
|
||||
node scripts/check_frontend.mjs --inventory
|
||||
|
||||
ENDPOINT_URL=http://127.0.0.1:1 node --test \
|
||||
tests/frontendArchitecture.test.mjs tests/noteTestOracle.test.mjs \
|
||||
tests/notesDraftAutosave.test.mjs tests/selectedNotesContext.test.mjs \
|
||||
tests/notesCharacterization.test.mjs tests/notesRecurrence.test.mjs \
|
||||
tests/notesInfrastructure.test.mjs tests/notesApplication.test.mjs \
|
||||
tests/notesReminders.test.mjs tests/notesWorkflows.test.mjs
|
||||
|
||||
CHROMADB_HOST=127.0.0.1 CHROMADB_PORT=1 \
|
||||
python -m pytest -q -rs \
|
||||
$(rg --files tests -g 'test_*note*.py') \
|
||||
tests/test_frontend_build.py tests/test_frontend_foundation_offline_js.py \
|
||||
tests/test_frontend_module_graph.py tests/test_frontend_module_version_parity.py \
|
||||
tests/test_panel_loader_js.py
|
||||
|
||||
python scripts/verify_frontend_runtime.py
|
||||
python scripts/verify_notes_browser_runtime.py
|
||||
|
||||
docker run --rm --network none \
|
||||
--mount type=bind,src="$PWD",dst=/candidate,readonly \
|
||||
--workdir /candidate --entrypoint python \
|
||||
<existing-odysseus-image> scripts/verify_frontend_runtime.py
|
||||
|
||||
CHROMADB_HOST=127.0.0.1 CHROMADB_PORT=1 \
|
||||
ODYSSEUS_STARTUP_WARMUPS=0 ODYSSEUS_TOOL_INDEX_PREWARM=0 \
|
||||
python -m pytest -q -rfs
|
||||
|
||||
git diff --check
|
||||
```
|
||||
|
||||
`ENDPOINT_URL` satisfies the existing oracle's import configuration; its endpoint-
|
||||
driving main does not run in these unit tests. Port 1 is the closed loopback target
|
||||
used for pytest; the two runtime scripts reserve their own non-listening Chroma port.
|
||||
The native browser script creates a private distribution/database and a temporary
|
||||
authenticated user, then terminates the server and removes that fixture. It uses
|
||||
the real application and Notes API rather than mocked browser routes.
|
||||
|
||||
The deterministic browser harness uses stub API responses and the real Notes ESM,
|
||||
DOM and stylesheet graph. It verifies namespace/default methods and arities,
|
||||
aliases, remount/search reset, rejected/accepted attachments, draft persistence,
|
||||
drawing/undo and listener/portal cleanup. It also checks larger-touch reorder after
|
||||
re-render, active-drag close cleanup and cancellation of a mobile selection hold.
|
||||
It includes the mobile viewport meta tag,
|
||||
tap-to-read/edit behavior and the existing selection jiggle. The original monolith
|
||||
can be replayed with `NOTES_BASELINE=1`; it is read from the frozen F1 revision.
|
||||
|
||||
## Browser and packaging evidence
|
||||
|
||||
Actual app screenshots: [desktop](evidence/notes/native-desktop.png) and
|
||||
[mobile](evidence/notes/native-mobile.png). These are Chromium screenshots of the
|
||||
disposable authenticated app at 1440 x 1000 and 390 x 844, not rendered mockups.
|
||||
The deterministic before/after fixture had an identical mobile PNG and only 14
|
||||
changed desktop pixels in the header region; no layout/style change was observed.
|
||||
CSS, app bootstrap and HTML have no implementation diff.
|
||||
|
||||
The native and Docker distribution probe serves all manifest outputs without
|
||||
`frontend/`, `node_modules/` or Node on the server path. It checks response bytes,
|
||||
JS MIME, revalidation, CSP, shell startup, static confinement and source-tree 404.
|
||||
Docker used existing image
|
||||
`sha256:cc2d47e2327d573af01c6b027f23d2ab0f2ee9b85d658e9eb8065bd02b9c3515`.
|
||||
This is not a fresh Dockerfile build or deployment.
|
||||
|
||||
Tested locally: Linux, Python 3.14.4, Node 22.23.1 and Playwright/Chromium 1.62.1.
|
||||
CI's exact Python 3.11/Node 20 pair, Firefox/WebKit, macOS/Windows executable builds,
|
||||
live model/email notification delivery and full root offline reload were not run.
|
||||
The Docker runtime uses its own existing dependency versions. Shared active-window
|
||||
gesture interleavings are not exhaustively covered. No broader platform certification
|
||||
is claimed.
|
||||
|
||||
The full-run safety overrides differ from official CI's plain pytest command.
|
||||
For the readiness default-contract check, use
|
||||
`env -u ODYSSEUS_TOOL_INDEX_PREWARM python -m pytest -q tests/test_readiness.py`.
|
||||
Keep explicit warmup/storage isolation on the disposable live-app probes.
|
||||
|
||||
## Internal checkpoints
|
||||
|
||||
Checkpoint snapshots are kept with the maintainer handoff, not in the repository.
|
||||
The hashes below identify them. They contain scoped source/output/facade/manifest/test
|
||||
overlays, not secrets or user data. Each starts from the same frozen baseline; they
|
||||
are not separate PRs or release candidates.
|
||||
|
||||
| Stage | Boundary and executed exit evidence | Snapshot SHA-256 |
|
||||
| --- | --- | --- |
|
||||
| N0 | Public/consumer/state/lifecycle map; 95 baseline Python and 11 Node passes; four new characterization tests; desktop/touch harness; 33 F1 publication/graph checks | `db0a2e6e68fec3442ce350ffb0acf47bcdf2a5266f7c64c2bf910a1c41c4fb62` |
|
||||
| N1 | Pure recurrence/date rules; eight Node and nine focused Python passes; differential oracle in four time zones; parity/boundaries | `fd0638470744706fbbd5787cb47bd2078a93c9b854139f89f8fdc169c1f353c6` |
|
||||
| N2 | HTTP/storage adapters; fourteen Node and seven focused Python passes; exact requests, keys and fallback contracts | `30826fb7972d1b9e3a790f97ee81f66dcb3dc58eb7d23e24d4f46e6d841b7c73` |
|
||||
| N3 | Single state owner and CRUD/undo boundary; ten Node and seven focused Python passes; read-only state and archive rollback | `4bc5293519b8438d0126a61887bea64195dcdb7d59bcfaaba8ed4ae8c38be439` |
|
||||
| N4 | Page-owned reminder workflow; four reminder contract tests and seven focused Python passes; singleton interval, catch-up, markers and fallback | `febb835c4958c8758e4b7c23ce89f3ec8d103c2cc28f89817d258b3791a9fcdf` |
|
||||
| N5 | Complete UI/application integration; 44 Node passes, targeted source guards and actual browser checks; drawing binding correction, read-only state and disposal | `e147f645bdb2161a4b1dc6cf10c36ba6d0c214d8e12fccb478835043eaaf3e94` |
|
||||
| N6 | Final facade, identity, exact offline graph, native/Docker checks, final editor-deletion/reorder ownership review, touch cleanup regression checks and maintainer review package | `c450e91f9fbfe5f0cd805e596b92a76383f22a74e9515ca3e3f6154aebf5f61f` |
|
||||
|
||||
The N6 overlay contained the final code, tests, manifest and attributes at
|
||||
publication, not the evidence directory itself. From the repository root, run
|
||||
`sha256sum -c docs/frontend-architecture/evidence/notes/implementation.sha256`
|
||||
to verify the current implementation files.
|
||||
|
||||
No checkpoint commits were made. To reproduce an overlay, create a fresh temporary
|
||||
directory, extract `git archive 1cc56cb9...` there, then extract the desired
|
||||
snapshot from the handoff on top. Install the locked test dependencies
|
||||
in that fixture and run its relevant commands. Begin from the baseline rather than
|
||||
overlaying snapshots onto a later dirty tree. For live rollback, release a complete
|
||||
matching artifact through the authorized release workflow.
|
||||
|
||||
Temporary mechanical extraction scripts are not part of the supported deliverable.
|
||||
They were archived locally, then removed. The first generated patch accidentally targeted
|
||||
the separate foundation worktree; only those edits were reversed, absolute paths
|
||||
were adopted, and that worktree's clean state was verified afterward.
|
||||
|
||||
## Open PR overlaps and handoff limits
|
||||
|
||||
The following remained open at the read-only GitHub refresh:
|
||||
|
||||
- [#6585](https://github.com/odysseus-dev/odysseus/pull/6585): optional Notes field removal in the backend. Existing null-field behavior is retained here.
|
||||
- [#6647](https://github.com/odysseus-dev/odysseus/pull/6647): read-only Notes intent routing.
|
||||
- [#6652](https://github.com/odysseus-dev/odysseus/pull/6652): `manage_notes` registry dispatch.
|
||||
- [#6470](https://github.com/odysseus-dev/odysseus/pull/6470): shared theme, typography, sidebar and modal changes.
|
||||
- [#6695](https://github.com/odysseus-dev/odysseus/pull/6695): extension system/platform integration.
|
||||
|
||||
Their changes were not merged or reimplemented. Shared UI exceptions, root-SW scope,
|
||||
the original last-completion fetch race, temporary-note correlation and canvas-draft
|
||||
limits are documented in the case study. Backend owner checks and PR #6495 contracts
|
||||
remain authoritative.
|
||||
Reference in New Issue
Block a user