mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-15 03:12:21 +02:00
refactor(frontend): establish source ownership and architecture gates (#6701)
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
# ADR 001: Feature-first native ESM with controlled deployment output
|
||||
|
||||
Date: 2026-10-13. Status: implemented F1 proof, proposed for maintainer adoption.
|
||||
Baseline: official `upstream/dev` at `8feb50e89468235cd3e0986da80edbd3acaf2c40`.
|
||||
Scope: source ownership and distribution foundation. Notes implementation is deferred.
|
||||
|
||||
## Decision
|
||||
|
||||
Maintain migrated JavaScript in `frontend/src/`. Publish native ES modules to
|
||||
explicitly registered paths in `static/js/`, and commit source and output together.
|
||||
Use `python scripts/build_frontend.py` to copy bytes without rewriting imports,
|
||||
bundling, minification, source maps, timestamps or generated headers. A checked-in
|
||||
`frontend/modules.json` maps source paths to deployment paths. All other static
|
||||
files remain authored legacy modules or deployment assets until a reviewed slice
|
||||
transfers their ownership. Do not claim that the whole static tree is generated.
|
||||
|
||||
The proof transfers maintenance of the stateless action-menu ordering helper to
|
||||
`frontend/src/shared/actionMenuOrder.js`. Its output remains
|
||||
`/static/js/actionMenuOrder.js`, with the same three exports and identical bytes.
|
||||
All seven current consumers, HTML, service worker and runtime entry points retain
|
||||
their existing URLs. There is no wrapper, extra request or second browser module
|
||||
instance. The source copy is a development input, not a second runtime entry point.
|
||||
|
||||
Use `frontend/src/app/` for composition, `features/<feature>/index.js` for feature
|
||||
public APIs, and responsibility directories only when implementation requires
|
||||
them. The [handbook](handbook.md) defines dependency, ownership and lifecycle rules.
|
||||
F1 creates only the shared proof, without empty application or feature scaffolding.
|
||||
|
||||
## Evidence and alternatives
|
||||
|
||||
Both options were executed against this helper, rather than assumed to work.
|
||||
Measurements are local compatibility observations, not general performance claims.
|
||||
|
||||
| Property | Controlled native ESM copy, selected | esbuild 0.25.12 controlled ESM build |
|
||||
| --- | --- | --- |
|
||||
| Proof output | 1,688 bytes, identical SHA-256 to existing runtime | 1,554 bytes with `--bundle --format=esm --target=es2022 --platform=browser` |
|
||||
| Repeatability | Clean temporary publication and idempotent rerun tested | Two independent compiler invocations emitted identical bytes |
|
||||
| Runtime contract | Existing exports, imports, cache entry and module identity unchanged | Export names, icon and ordering matched in an executed Node import |
|
||||
| Tooling | Python standard library; no production dependency | Compiler and platform binary needed for artifact production |
|
||||
| Local cost | Copy check: 0.03 s, 15,596 KB maximum RSS | Cached `npx` ESM transform: 0.58 s, 114,196 KB maximum RSS |
|
||||
| Incremental migration | Explicit file ownership, preserved module boundaries | Feasible for the stateless leaf; stateful facade/chunk identity still needs a separate graph spike |
|
||||
| Release implications | Commit output; install/startup paths consume existing static assets | Would also need committed or release-produced output plus compiler locking and facade/chunk manifest policy |
|
||||
|
||||
The timing rows measure different tool paths, including `npx` overhead. The
|
||||
compiler's single-leaf success does not establish stateful graph or lazy chunk
|
||||
compatibility. The 134-byte bundle reduction does not justify that additional
|
||||
contract in F1. A future compiler adoption requires a new ADR and graph-level
|
||||
evidence. React, Vue, TypeScript, a global state library, hashed chunks and a
|
||||
development server have no demonstrated necessity here.
|
||||
|
||||
Acorn 8.19.0 is added only as an exact, lockfile-pinned development dependency for
|
||||
architecture checks. A real JavaScript parser is needed to enforce boundaries
|
||||
across multiline imports, re-exports and lazy thunks without treating comments
|
||||
and string literals as executable imports. It is MIT licensed, about 568 KB
|
||||
unpacked, and contributes no deployed JavaScript or runtime dependency.
|
||||
|
||||
## Distribution contract
|
||||
|
||||
1. Source and generated output are reviewed and committed together. CI checks
|
||||
byte parity; it does not silently rebuild and accept drift.
|
||||
2. Native Python startup continues to use `STATIC_DIR` and `/static`, without
|
||||
invoking the publisher. Native installers already obtain tracked static files.
|
||||
3. Docker's current `COPY . .` includes the output. `.dockerignore` excludes
|
||||
`node_modules/`. The Docker runtime and entrypoint require no frontend build.
|
||||
4. `Odysseus.spec` and `build-windows-portable.ps1` already include `static/`.
|
||||
The macOS wrapper uses the Python checkout and its static assets. Neither
|
||||
needs the source tree or frontend tooling to serve the proof.
|
||||
5. A release producer runs the checks before packaging and distributes the
|
||||
entire matching static graph. The publisher is not a transactional deployment
|
||||
mechanism. Partial copying of a new graph into a live deployment is unsupported.
|
||||
6. New output paths must declare LF checkout behavior in `.gitattributes`, as
|
||||
this proof does, so Windows checkout conversion cannot create false byte drift.
|
||||
Before checking parity or writing output, the publisher uses the manifest to
|
||||
require effective `text: set` and `eol: lf` on every source/output path. It asks
|
||||
Git in a temporary repository containing only the applicable repository-owned
|
||||
`.gitattributes` files, including nested rules. Global/local Git overrides
|
||||
cannot supply missing declarations. No blanket legacy-JS rule is introduced.
|
||||
Git is a development/publication prerequisite, not a startup dependency.
|
||||
|
||||
An isolated distribution probe executes the real FastAPI lifespan, shell and
|
||||
static requests after omitting `frontend/` and `node_modules/` and removing Node
|
||||
from the child process search path. It verifies bytes, MIME, CSP, revalidation,
|
||||
source-tree 404 behavior and static path confinement. The same probe runs in an existing Docker image
|
||||
with networking disabled. This is not a claim that a fresh full Docker image or
|
||||
Windows/macOS executable was built; see [validation](validation.md).
|
||||
|
||||
## Imports, identity and offline operation
|
||||
|
||||
New maintained modules use one unversioned deployment URL. Existing legacy URLs,
|
||||
including their version queries, stay unchanged. A copy mapping must preserve
|
||||
the resolution of every literal relative import; the architecture checker rejects
|
||||
a mapping that changes that resolution. Canonical absolute `/static/js/...`
|
||||
imports are also supported. No bare packages or browser imports of `frontend/src`
|
||||
are supported. Existing graph and identity guards continue to cover the runtime.
|
||||
|
||||
Each registered output joins the exact `PRECACHE` or `PANEL_PRECACHE` array. The
|
||||
new checker parses those arrays, rather than accepting a URL mentioned in a
|
||||
comment. Installation fetches do not evaluate lazy modules. Import-time DOM work,
|
||||
timers, state creation and network I/O must be characterized before changing an
|
||||
entry point's load timing. New source dependency cycles are rejected; existing
|
||||
legacy cycles are inventoried and remain outside the new rules.
|
||||
|
||||
The proof already has its exact precache entry, so no SW cache-name or HTML edit
|
||||
is needed. Its first evaluation in a fresh offline browser page passes, and
|
||||
importing the panel registry does not evaluate the editor. The current worker's
|
||||
`/static/` scope cannot control the SPA root. Open PR #6227 addresses that existing
|
||||
limitation; F1 does not fix or mask it. Full root offline reload is not certified.
|
||||
|
||||
## Security and compatibility
|
||||
|
||||
Keep backend authorization and owner scope authoritative. No agent, database,
|
||||
auth, CSP, static mount or API implementation changes belong to this decision.
|
||||
The helper remains same-origin ESM without eval, compiler runtime or external
|
||||
resources. No new source maps or vendored assets are emitted; existing SRI/CSP
|
||||
policy and distribution notices remain unchanged. The publisher validates path
|
||||
containment, symlinks, duplicate ownership and unmapped source before writing.
|
||||
It never deletes unowned static assets. Deleting or retiring outputs is an
|
||||
explicit reviewed migration operation, not automatic cleanup.
|
||||
|
||||
## Rollout, rollback and limits
|
||||
|
||||
Adopt F1 for controlled, reviewed slices after maintainer review. Leave Notes,
|
||||
bootstrap, HTML and service worker unchanged here. Register new files explicitly;
|
||||
update offline manifests only when new runtime dependencies are introduced.
|
||||
F1 rollback can remove the source manifest, proof tooling, gates and documentation
|
||||
without changing runtime bytes. Later rollback restores the complete prior
|
||||
source/output/facade/precache set through an authorized follow-up change.
|
||||
|
||||
Boundary gates cannot prove semantic purity, owner isolation or correct teardown.
|
||||
Domain platform/clock checks are intentionally conservative syntax guards;
|
||||
behavior tests still establish those contracts. Worker URLs, styles and vendored
|
||||
libraries are outside the maintained-JS import gate and need explicit review if
|
||||
a future lane changes them. Legacy exceptions require an exact specifier and a
|
||||
module-scoped reason; there are none in F1. New source is not permission to
|
||||
grandfather new dependency cycles or to replicate broadly shared mutable state.
|
||||
@@ -0,0 +1,127 @@
|
||||
# F1 runtime and architecture assessment
|
||||
|
||||
Assessment date: 2026-10-13. Repository: `odysseus-dev/odysseus`.
|
||||
Worktree: `worktrees/architecture/frontend-foundation`.
|
||||
Branch: `refactor/frontend-architecture-foundation`.
|
||||
HEAD, local `upstream/dev`, and the live GitHub official `dev` commit were all
|
||||
`8feb50e89468235cd3e0986da80edbd3acaf2c40`. The initial worktree was clean.
|
||||
That commit is the merged PR #6495, selected Notes/Todos agent context.
|
||||
`origin` points to the maintainer fork; integration targets official `upstream/dev`.
|
||||
|
||||
Inputs read completely: the 2026-10-13 frontend architecture RFC and coding brief
|
||||
from Downloads, `specs/frontend.md`, repository instructions and existing tests.
|
||||
The current user brief supersedes the coding brief's `origin/dev` wording and
|
||||
defines the Notes state/workflow slice before reminders. The design is self-contained
|
||||
in this directory and does not require access to Downloads.
|
||||
|
||||
Input provenance:
|
||||
|
||||
- RFC SHA-256: `11dedcbb9971f4d787f2721b9c27aa43299baba39ca91066d01507d2d69ac4f8`.
|
||||
- Coding brief SHA-256: `e4882867617b9c732ce4f445e3bc2da0b4ec1315119f8226c1fd8c1acbacf29d`.
|
||||
|
||||
## Module graph and bootstrap
|
||||
|
||||
`node scripts/check_frontend.mjs --inventory` reproduces the parser-based inventory.
|
||||
It excludes vendored `static/lib/` and committed editor build output. At this base
|
||||
it scans 230 JS files, finds 707 static import/re-export edges and 108 literal
|
||||
dynamic import edges, and finds no missing targets. No computed dynamic imports
|
||||
were found in the original parser audit. The earlier existing-regex scan counted
|
||||
814 edges; executable syntax parsing counts 815. Use parser evidence for design
|
||||
and retain the existing regression guard unchanged.
|
||||
|
||||
| Area | Current boundary and implication |
|
||||
| --- | --- |
|
||||
| HTML shell | `static/index.html`: nonce-bearing boot scripts, CSS/preloads, direct ESM script tags, then app/init/a11y. Multiple entry roots mean module identity matters. |
|
||||
| App composition | `static/app.js`: feature imports, globals, route/sidebar composition, session hydration and auth-fetch wiring. It eagerly imports Notes, Calendar, Chat, Documents and Settings. |
|
||||
| Startup | `static/js/startupShell.js`, `sessions.js`, `init.js`: first-paint scheduling, deferred hydration, user-switch storage cleanup and cosmetic permission gates. Preserve boot ordering. |
|
||||
| Lazy loading | `static/js/panels.js`: only `editor` is registered. A memoized import thunk shares successful/in-flight promises and retries failed imports. Do not label all panels lazy. |
|
||||
| Optional libraries | `markdown.js` lazily loads vendored KaTeX/Mermaid. KaTeX and fonts are precached; Mermaid becomes cached after first use. Pyodide has a CDN dependency. |
|
||||
| Feature packages | Settings registry/navigation/finder/lifecycle, Calendar utilities/reminders, Email wrapper/package and editor tools already demonstrate partial decomposition. |
|
||||
|
||||
Highest import fan-in: `ui.js` 77, `spinner.js` 55, `editor/state.js` 39,
|
||||
`escMenuStack.js` 23, and storage/modal/z-order helpers 17 each. The measured
|
||||
static strongly connected components are:
|
||||
|
||||
- Theme and UI.
|
||||
- Email Inbox, compatibility wrapper, package index, AI reply, attachments,
|
||||
body rendering, menus, reader, settings page and unsubscribe.
|
||||
- Cookbook, diagnosis, HW Fit, download, running and serve modules.
|
||||
|
||||
These are existing compatibility constraints, not approved patterns for new
|
||||
source. Dynamic edges connect more features but do not themselves establish
|
||||
initialization cycles. No global legacy dependency rewrite is attempted in F1.
|
||||
|
||||
## State, side effects and ownership
|
||||
|
||||
| Owner | Evidence and architectural treatment |
|
||||
| --- | --- |
|
||||
| Shared configuration | `appConfig.js` owns invalidatable settings/tool request promises and consumes a sessionStorage prefetch once. Retain single identity and writer invalidation. |
|
||||
| Browser persistence | `storage.js` centralizes keys and safe access; feature files also use direct localStorage. `init.js` cleans storage on user changes. Preferences are not an authorization store. |
|
||||
| Feature state | Notes has module variables, selection sets, undo/drafts and reminder state. Email exports a broadly mutable package state object; editor state is imported by 39 modules. Keep ownership explicit; do not expand these into a global store. |
|
||||
| Import-time effects | Notes reads storage/window and schedules reminders. Email state reads localStorage. Theme/UI initialize from DOM readiness; modal manager installs global listeners. Chip/mobile helpers bind at startup. Moving an import can change behavior before any exported function is called. |
|
||||
| Compatibility globals | App exposes controllers on `window`; Notes exposes `window.notesModule`. They are compatibility bridges, not the new inter-feature API convention. |
|
||||
| Async ownership | Session hydration, config invalidation, draft serialized saves and request-generation guards already prevent stale completion. New slices must preserve these rather than only move declarations. |
|
||||
|
||||
Good patterns to retain: narrow zero-state leaves, explicit wrapper export lists,
|
||||
public API tests, retryable memoized lazy imports, shared config invalidation,
|
||||
request-generation checks and source/package-aware regression helpers.
|
||||
|
||||
Patterns to avoid: blanket barrels exposing internals, feature imports from
|
||||
generic helpers, cycles through coordinators, direct writes to another feature's
|
||||
state or DOM, anonymous global listener ownership, import-triggered network/timer
|
||||
initialization in new APIs, and helpers grouped by convenience instead of purpose.
|
||||
|
||||
## Runtime, assets and distribution
|
||||
|
||||
| Contract | Verified source |
|
||||
| --- | --- |
|
||||
| Static URL and revalidation | `app.py`: `register_static_mime_types`, `_RevalidatingStatic`, `/static` mount. JS MIME is `text/javascript`; JS/CSS/HTML have `Cache-Control: no-cache`. |
|
||||
| App paths | `src/constants.py` and `src/runtime_paths.py`: checkout root in native mode, PyInstaller `_MEIPASS` in frozen mode; static assets follow app root, persisted data follows data-directory policy. |
|
||||
| CSP | `core/middleware.py`: same-origin scripts, nonce and jsDelivr allowance; `src/app_helpers.py` injects HTML nonces. No CSP relaxation is needed for the proof. |
|
||||
| Integrity | No `integrity=` attributes were found in the shell. Proof output is byte-identical and emits no source maps; no existing SRI or vendored artifacts change. |
|
||||
| Runtime-generated assets | `/api/generated-image/...` uses a confined data path and owner handling; report/render endpoints, Blob manifests/icons and uploads are runtime concerns outside static source publication. |
|
||||
| Docker | `Dockerfile` copies app code and existing static output; `.dockerignore` excludes node_modules. Node/npm in the image support Browser MCP, not frontend startup. |
|
||||
| Native installers | `setup.py`, `start-macos.sh`, `launch-windows.ps1`, systemd service: Python dependencies/startup consume the checkout. No frontend build is invoked. |
|
||||
| Windows desktop | `Odysseus.spec` and `build-windows-portable.ps1` include the whole static directory. Maintain output here rather than require a new bundle path or compiler. |
|
||||
| macOS | `build-macos-app.sh` creates a launcher around the Python checkout. Static serving follows the existing checkout path. Installer execution was not performed on Linux. |
|
||||
|
||||
## PWA limitations and test coverage
|
||||
|
||||
`static/sw.js` matches exact URLs, including queries. Install fetches each
|
||||
precache entry separately and tolerates failed fetches. It does not discover
|
||||
transitive dependencies. HTML root and JS/CSS handlers are network-first;
|
||||
other static assets are cache-first with background refresh. API and non-GET
|
||||
requests bypass caching. Cache updates need explicit version/manifest review.
|
||||
The older frontend spec's root stale-while-revalidate description is stale.
|
||||
|
||||
Registration in `static/index.html` currently requests no wider scope, so the
|
||||
worker controls `/static/`, not `/`. Root offline reload is therefore a known
|
||||
pre-existing gap. PR #6227 proposes the scope/header correction. F1 tests actual
|
||||
offline ESM loading under the current scope and leaves that separate fix alone.
|
||||
Offline APIs, first-use Mermaid and optional CDN runtimes are not certified.
|
||||
|
||||
Existing coverage includes runtime graph resolution and version parity; editor
|
||||
offline graph coverage and lazy-loader retries; Email API/export/evaluation
|
||||
coverage; Notes autosave, XSS, selection/listener and agent-context regressions;
|
||||
MIME, nonce and runtime paths. Tests use pytest, Node's built-in runner and existing
|
||||
Playwright Chromium. `tests/TESTING_STANDARD.md` requires behavior-first, isolated
|
||||
tests. F1 adds real publication failures, architecture violations and an offline
|
||||
browser proof. It does not replace existing source-sensitive tests.
|
||||
|
||||
## Open PR overlap, checked live on 2026-10-13
|
||||
|
||||
The open-PR listing was fetched through all pages; selected PR file lists were
|
||||
inspected. Refresh this inventory before any later slice.
|
||||
|
||||
| PR | Overlap and disposition |
|
||||
| --- | --- |
|
||||
| [#6470](https://github.com/odysseus-dev/odysseus/pull/6470) | Theme/sidebar redesign touches HTML, SW, shared UI and CSS. F1 changes none of those assets. Future manifest/UI slices need collision review. |
|
||||
| [#6695](https://github.com/odysseus-dev/odysseus/pull/6695) | OXS touches bootstrap, HTML, platform, middleware and other backend boundaries. F1 does not establish an extension API or modify that platform. |
|
||||
| [#6227](https://github.com/odysseus-dev/odysseus/pull/6227) | Root SW scope/header fix. Independent follow-up dependency for broader offline certification. |
|
||||
| [#6394](https://github.com/odysseus-dev/odysseus/pull/6394) | Older CSS extraction touches legacy style/SW assets; requires separate supersession review. |
|
||||
| [#6627](https://github.com/odysseus-dev/odysseus/pull/6627) | npm development-dependency update overlaps package/lock files; reconcile the exact Acorn development entry on integration. |
|
||||
| [#6585](https://github.com/odysseus-dev/odysseus/pull/6585), [#6647](https://github.com/odysseus-dev/odysseus/pull/6647), [#6652](https://github.com/odysseus-dev/odysseus/pull/6652) | Notes optional-field persistence and agent routing/dispatch. Future characterization must reflect their merged state; F1 changes no Notes or backend behavior. |
|
||||
| [#6594](https://github.com/odysseus-dev/odysseus/pull/6594), [#6152](https://github.com/odysseus-dev/odysseus/pull/6152) | Desktop launcher/build and frozen-runtime packaging work. Existing paths stay stable; packaging still needs platform-owner validation. |
|
||||
|
||||
PR titles alone do not establish compatibility. This report records the checked
|
||||
file overlap and relevant dependencies, not approval of those implementations.
|
||||
@@ -0,0 +1,223 @@
|
||||
# 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.
|
||||
|
||||
Read the [ADR](ADR-001-source-and-deployment.md), [assessment](assessment.md),
|
||||
[validation report](validation.md) and [Notes roadmap](notes-roadmap.md).
|
||||
The frontend program ends with the Notes reference decomposition and handoff.
|
||||
Calendar, Documents, Email, Chat, Skills, Settings and other later decompositions
|
||||
belong to the designated frontend maintainer; do not start them automatically.
|
||||
|
||||
## Source, ownership and public APIs
|
||||
|
||||
`frontend/src/app/` composes public feature APIs and platform ports. Each
|
||||
`features/<feature>/index.js` is an intentional API, with explicit named exports
|
||||
and a compatibility default only when existing consumers require one. Internals
|
||||
live under `domain/`, `application/`, `infrastructure/` or `ui/` as needed. Do not
|
||||
create empty directories, boilerplate controllers or a framework by convention.
|
||||
Feature names `app` and `shared` are reserved.
|
||||
|
||||
Keep pure business rules in domain; transitions and workflows in application;
|
||||
HTTP/storage/browser services in infrastructure; DOM rendering and lifecycle in
|
||||
UI. The index composes adapters, state and views. Application receives adapters
|
||||
as explicit arguments or constructor ports, rather than importing concrete
|
||||
infrastructure. Views call application operations; infrastructure does not own
|
||||
business decisions. A public API returns data/operations, not mutable stores or
|
||||
private DOM nodes. Importing an API should define capabilities; explicit lifecycle
|
||||
methods activate them. Legacy side effects remain characterized until a reviewed
|
||||
slice safely changes their placement.
|
||||
|
||||
Shared code has a named, proven cross-feature responsibility. `shared/domain/`
|
||||
holds pure primitives, `shared/platform/` holds narrowly scoped platform adapters,
|
||||
and `shared/ui/` holds common DOM capabilities. A named stateless root leaf such
|
||||
as `shared/actionMenuOrder.js` is also allowed and receives domain restrictions.
|
||||
Do not create a central `utils.js` collection or move feature business rules into
|
||||
shared simply to satisfy an import rule.
|
||||
|
||||
## Mechanically checked dependency contract
|
||||
|
||||
| Importer | Permitted maintained-source targets |
|
||||
| --- | --- |
|
||||
| App composition | Other app code, shared code, feature `index.js` APIs |
|
||||
| Feature index | Its own responsibility modules and shared code; other feature public indexes |
|
||||
| Feature domain | Its own domain and shared domain/stateless leaves |
|
||||
| Feature application | Its own application/domain, shared domain, other feature public indexes |
|
||||
| Feature infrastructure | Its own infrastructure/domain, shared domain/platform |
|
||||
| Feature UI | Its own UI/application/domain, shared domain/platform/UI |
|
||||
| Shared domain leaf | Shared domain leaves only |
|
||||
| Shared platform | Shared platform/domain only |
|
||||
| Shared UI | Shared UI/platform/domain only |
|
||||
|
||||
No feature imports app composition. No shared code imports a feature. No external
|
||||
feature imports private responsibility modules. UI and infrastructure communicate
|
||||
with another feature through a supplied application operation/port. Maintained
|
||||
source dependency cycles, including literal lazy imports, fail the architecture
|
||||
gate. If features need bidirectional coordination, app composition injects a
|
||||
callback or adapter instead of creating mutual imports. Prefer this even when a
|
||||
one-way public index import would pass the gate.
|
||||
|
||||
Cross-feature events must document event name, payload, acknowledgement, owner,
|
||||
subscription disposal and delivery timing. Keep them local and specific; F1 adds
|
||||
no global event bus. Preserve `odysseus:notes-context-selected` and its synchronous
|
||||
`accepted` acknowledgement in future Notes work. The server remains authoritative
|
||||
for owner filtering and untrusted selected IDs. Frontend APIs cannot grant access.
|
||||
|
||||
The checker parses executable ESM, forbids computed imports in new source,
|
||||
requires exact precache entries, rejects unresolved/remapped relative imports,
|
||||
and permits only canonical static JS URLs with one unversioned identity for
|
||||
maintained modules. Domain code cannot mention known browser/HTTP/timer globals
|
||||
or an ambient clock; use `now`/clock inputs. This is a conservative vocabulary
|
||||
check, including shadowed names, not a semantic purity proof. Randomness, hidden
|
||||
side effects, authorization and lifecycle behavior require behavioral tests.
|
||||
|
||||
Legacy imports from new source default to forbidden. If an incremental bridge is
|
||||
necessary, declare `legacyImports` on that source's manifest entry as a list of
|
||||
`{ "specifier": "/static/js/example.js?v=existing", "reason": "contract, owner and removal slice" }`.
|
||||
Only feature composition, infrastructure or UI boundaries may use it. Exact
|
||||
specifier/reason and target existence are required; unused exceptions fail.
|
||||
Keep the existing query identity. New domain/application modules receive no
|
||||
legacy exception. F1 has zero exceptions. Do not use exceptions to invent new
|
||||
shared platform dependencies on feature internals.
|
||||
|
||||
## State and lifecycle
|
||||
|
||||
Each feature has one authoritative mutable application-state owner. A transition
|
||||
operation owns writes; UI receives a view/snapshot or subscription. Preserve
|
||||
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.
|
||||
|
||||
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
|
||||
resources it owns. Background reminders may outlive an open panel. Closing the
|
||||
panel must not silently stop those reminders during extraction.
|
||||
|
||||
Keep request-generation and selected-session checks around asynchronous
|
||||
completions. Serialize writes where the current contract requires it. Dispose
|
||||
subscriptions explicitly and prevent late updates to a replaced view. Feature
|
||||
state changes on user/session switch must follow current cleanup policy. Browser
|
||||
storage is for preferences/drafts/cache state, never a substitute for backend
|
||||
authorization, credential storage or owner filtering. Define every storage key's
|
||||
owner, retention/reset behavior and compatibility format before moving it.
|
||||
|
||||
## Creating a module or introducing a feature
|
||||
|
||||
1. Identify responsibility, owner, public consumers, side effects and behavioral
|
||||
evidence before editing. Start with a pure leaf when introducing a feature.
|
||||
2. Place only the required source file(s), for example
|
||||
`features/example/domain/calculate.js`. Add an index only when there is a
|
||||
real supported feature API to compose.
|
||||
3. Register each source in `frontend/modules.json`. A typical new mapping is
|
||||
`features/example/domain/calculate.js` to
|
||||
`js/features/example/domain/calculate.js`. Preserve the source/deployment
|
||||
relative graph. The proof's legacy URL mapping is an explicit special case.
|
||||
4. For an extracted leaf, the legacy feature coordinator may import its output
|
||||
as a temporary composition bridge. New maintained features use public indexes;
|
||||
the legacy tree is not globally forced into the new boundary rules in F1.
|
||||
5. Add the exact output URL to the appropriate explicit SW array, retain lazy
|
||||
evaluation timing and bump the cache name when the graph changes. Declare
|
||||
`text eol=lf` for both mapped paths in repository-owned `.gitattributes`
|
||||
files; source-tree or scoped output patterns are allowed. The publisher checks
|
||||
effective Git rules, including nested overrides, and rejects a missing LF rule
|
||||
even if output bytes already match. Do not broaden unrelated legacy checkout
|
||||
rules or automatically rewrite all existing query identities.
|
||||
6. Run the publisher, inspect the source/output diff, then run architecture,
|
||||
identity, graph, offline and focused behavior checks. Include both sides of
|
||||
the mapping in review. Retiring output requires a separate reviewed deletion;
|
||||
the publisher does not clean the static tree.
|
||||
|
||||
```sh
|
||||
python scripts/build_frontend.py
|
||||
python scripts/build_frontend.py --check
|
||||
npm ci --ignore-scripts --no-audit --no-fund
|
||||
node scripts/check_frontend.mjs
|
||||
node scripts/check_frontend.mjs --inventory
|
||||
node --test tests/frontendArchitecture.test.mjs
|
||||
./venv/bin/python -m pytest -q -rs 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
|
||||
./venv/bin/python scripts/verify_frontend_runtime.py
|
||||
```
|
||||
|
||||
Use your actual repository virtualenv path; the F1 environment is recorded in
|
||||
validation. Node 20+ follows current CI. Existing Playwright/browser prerequisites
|
||||
are documented in `tests/README.md` and `tests/KNOWN_FAILURES.md`. Missing Node can
|
||||
skip Python browser wrappers, which is a coverage gap, not a pass. The standalone
|
||||
Node gates require locked development dependencies and fail when missing.
|
||||
|
||||
The publisher validates all inputs before writing and only overwrites owned
|
||||
outputs whose bytes differ. It is idempotent and working-directory independent.
|
||||
Git must be available for publication and `--check`; neither runs at application
|
||||
startup. Attribute evaluation uses a private temporary Git repository and ignores
|
||||
global/local overrides, so checkout consistency is reproducible in CI. It adds
|
||||
no runtime configuration or backend imports. CI checks LF attributes, parity and source
|
||||
syntax in existing jobs; the Node job also runs architecture self-tests. Existing
|
||||
runtime identity tests remain authoritative across legacy imports, HTML and SW.
|
||||
The isolated runtime probe is included in the new pytest publication tests.
|
||||
|
||||
## Review, release and rollback
|
||||
|
||||
Review the source/output mapping and exact exported API, then the owner/dependency
|
||||
contract and behavior tests. Check manifests, URL identities, MIME/CSP, load timing,
|
||||
storage compatibility and disposal. Reject unexplained feature behavior changes.
|
||||
Do not repair unrelated defects under an extraction title.
|
||||
|
||||
Release from a validated revision with committed output. Native startup and
|
||||
packagers consume static files without a compiler. Run parity before producing a
|
||||
Docker or desktop artifact. Test the actual packaged application on its platform;
|
||||
Linux contract probes cannot certify macOS/Windows executables. Deploy matching
|
||||
shell, facades, graph and manifests as a unit. Keep an authorized path to the last
|
||||
complete artifact. Rollback restores the whole matching set, not just an entry
|
||||
file or cache version. Do not delete a facade until its public consumers have
|
||||
migrated and compatibility tests make that decision reviewable.
|
||||
|
||||
## Proposal and PR templates
|
||||
|
||||
For a decomposition proposal, record: baseline; responsibility map; current public
|
||||
API and consumers; state owner; I/O and lifecycle boundaries; planned slice;
|
||||
allowed dependencies/temporary exceptions; preserved behavior; deterministic
|
||||
characterization tests; deployment/offline changes; overlapping PRs; rollback;
|
||||
explicit non-goals and remaining uncertainties.
|
||||
|
||||
For each migration PR, lead with the responsibility moved and resulting boundary.
|
||||
Record source/output paths, API compatibility, state/lifecycle ownership,
|
||||
characterization results, exact validation commands, platform gaps, exception
|
||||
removal plan, upstream dependencies and rollback. Attach a concrete before/after
|
||||
example when needed to establish behavioral equivalence. Preserve the repository
|
||||
PR template and never claim unexecuted checks.
|
||||
|
||||
F1 is an entirely separate foundation-only PR. Deliver the complete Notes
|
||||
decomposition, regression tests, compatibility validation and final reference
|
||||
case study through one draft PR targeting official `dev`, using one Notes branch
|
||||
and worktree after F1 integration. N0 through N6 and the N5 substages are internal
|
||||
engineering checkpoints, not independent PRs or merges. Each checkpoint records
|
||||
focused tests, review evidence, its validated revision or reproducible snapshot,
|
||||
and rollback to the prior matching source/output/facade/precache set. Keep the
|
||||
draft open while those checkpoints progress; mark it ready only after the entire
|
||||
decomposition passes the [roadmap's acceptance gates](notes-roadmap.md).
|
||||
|
||||
Structure the Notes PR description around the final integrated design and link
|
||||
each checkpoint's evidence. The receiving maintainer may use smaller independent
|
||||
PRs for future frontend features at their discretion; the one-PR Notes decision
|
||||
does not impose that delivery size on later work.
|
||||
|
||||
## Program backlog and final handoff
|
||||
|
||||
Priority order: review/integrate F1; resolve root offline certification with the
|
||||
owner of PR #6227; complete the Notes checkpoints and final reference case study
|
||||
within one draft PR following the [roadmap](notes-roadmap.md); integrate the
|
||||
complete Notes PR after its acceptance gates; finalize the recipient handoff.
|
||||
Only then does the receiving maintainer prioritize Calendar, Documents, Email,
|
||||
Chat, Skills and Settings against current behavior and risk. Existing partial
|
||||
packages and high fan-in helpers need assessment, not automatic replacement.
|
||||
|
||||
Final H acceptance requires a designated maintainer, the integrated Notes PR
|
||||
revision and its internal checkpoint receipts, the actual public API/state/lifecycle
|
||||
map and final reference case study included in that PR, validated deployment/offline
|
||||
commands, known exceptions/debt,
|
||||
outstanding PR dependencies, rollback evidence and a reproducible independent
|
||||
setup by the recipient. F1 provides the handbook structure and contracts; it does
|
||||
not claim Notes or the completed handoff have occurred. The initiating architect
|
||||
then returns to separately authorized non-frontend architecture work.
|
||||
@@ -0,0 +1,173 @@
|
||||
# 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.
|
||||
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`.
|
||||
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
|
||||
changes the contract everywhere.
|
||||
|
||||
| Responsibility | Current evidence | Intended owner after its reviewed slice |
|
||||
| --- | --- | --- |
|
||||
| State and CRUD | `_notes`, selection/filter/editing/loading variables, `_undoStack`, `_fetchNotes`, `_saveNote`, `_patchNote`, `_archiveNoteById` | One application state owner and workflow operations; no second reminder/UI copy |
|
||||
| Dates and recurrence | `_normalizeRepeat`, `_advanceRecurring`, `_nthWeekdayOfMonth`, `_lastWeekdayOfMonth`, `_toLocalDatetimeStr`, repeat formatting helpers | Pure domain calculations with explicit clock inputs |
|
||||
| Network and persistence | Notes CRUD/reorder, upload, reminder firing, draft and reminder localStorage keys | Infrastructure adapters preserving request payloads, credentials and error contracts |
|
||||
| Reminders | `_checkReminders`, `_startReminderLoop`, `_initReminders`, notification permission/display and due/fired badge calculations | Application reminder workflow plus injected clock/storage/notification/API ports |
|
||||
| Draft autosave | `_draftKey`, `_collectFormDraft`, `_wireDraftAutosave`, `_applyDraftToNote`, `_commitOpenInPlaceEditor` | Draft workflow with editor view/persistence ports and serialized saves |
|
||||
| UI | `openPanel`, `closePanel`, `_renderNotes`, forms/cards/checklists, masonry, color/photo/drawing, mobile swipe/reorder | Scoped UI modules with explicit mount/dispose and application operations |
|
||||
| Agent context | `#notes-send-agent` handler, selected IDs, `odysseus:notes-context-selected` | Preserve event payload and synchronous acknowledgement; Chat owns attachment/session state |
|
||||
| Agent solve action | `_agentSolveNote`: default-chat lookup, session creation and chat stream | Separate existing workflow; do not conflate with selected-note attachment |
|
||||
| Compatibility coordinator | Default controller, named aliases, `window.notesModule`, delayed reminder startup | Stable legacy facade/composition bridge until consumers safely migrate |
|
||||
|
||||
The default API currently includes `openPanel`, `closePanel`, `togglePanel`,
|
||||
`isPanelOpen`, `openNote`, `newNote`, `openNotes`, `closeNotes`, `isNotesOpen` and
|
||||
`refreshDueBadge`. Named exports also include `dismissFiredReminderDot` and the
|
||||
panel/open aliases. Characterization must pin the complete actual namespace and
|
||||
default object separately, including identity of aliases and the window bridge.
|
||||
|
||||
Consumers include `static/app.js` sidebar/routes/badge polling,
|
||||
`chatStream.js` note tool updates, `chatRenderer.js` note links and
|
||||
`document.js` coordination. `static/index.html` and `static/sw.js` are entry/cache
|
||||
contracts. The shared UI, confetti, modal, color picker, drag, tiling, docking,
|
||||
z-order and Escape helpers are direct dependencies. Those legacy dependencies
|
||||
remain in the coordinator until their ownership is reviewed, rather than moving
|
||||
all UI coupling into domain modules.
|
||||
|
||||
Import-time behavior includes window origin/storage reads and
|
||||
`setTimeout(_initReminders, 3000)`. The successful bootstrap loads Notes and starts
|
||||
a 30-second reminder interval. App composition separately refreshes the badge
|
||||
every five minutes. Panel/editing listeners, draft timers, highlight animations,
|
||||
ResizeObserver and drawing/touch handlers have shorter scopes. Record them before
|
||||
extraction; do not stop background reminders merely because a panel closes.
|
||||
Listener cleanup concerns require characterization, not an unrelated fix hidden
|
||||
inside an extraction.
|
||||
|
||||
Persistence includes `odysseus-notes-view`, label collapse and hint preferences,
|
||||
fired/glowed/pending/active reminder markers, dismissed timestamp, and
|
||||
`odysseus-note-draft-<id>` including `__new__`. Current direct APIs include Notes
|
||||
CRUD/reorder/fire-reminder and upload, plus default-chat/session/chat-stream for
|
||||
the existing solve action. Backend owner isolation and permission handling stay
|
||||
authoritative and are outside this frontend decomposition's implementation scope.
|
||||
|
||||
## PR #6495 contract that every relevant slice preserves
|
||||
|
||||
Notes sends `odysseus:notes-context-selected` with `{ noteIds, accepted: false }`.
|
||||
Chat's synchronous listener accepts only a valid active or pending chat, updates
|
||||
session/pending selection, sets `accepted`, and updates the context indicator.
|
||||
Notes clears select mode only after acceptance. Session lifecycle events
|
||||
`odysseus:session-changed` carry session/materialization information. Chat appends
|
||||
selected IDs as `selected_note_ids` when sending; server parsing validates IDs,
|
||||
filters by owner and treats the resulting prompt context as untrusted.
|
||||
|
||||
Keep selection transfer to a materialized chat, reset on a new chat, rejection
|
||||
when no chat/model can accept it, aliases and indicator behavior. Do not broaden
|
||||
frontend selections into permissions or bypass the backend. See
|
||||
`tests/selectedNotesContext.test.mjs`, `tests/test_selected_notes_context.py`,
|
||||
`static/js/chat.js` selected-context listeners and send payload, and
|
||||
`static/js/sessions.js` lifecycle event producers.
|
||||
|
||||
## One Notes branch, worktree and draft PR
|
||||
|
||||
After F1 integration and authorization to begin Notes, create one worktree and
|
||||
branch, suggested name `refactor/notes-reference-decomposition`, from the latest
|
||||
official `upstream/dev`. N0 through N6 are sequential internal engineering
|
||||
checkpoints on that same branch. No independent GitHub PR is required for a
|
||||
checkpoint or a UI substage. Maintain one draft PR targeting official `dev`, with
|
||||
checkpoint evidence linked from its description. Keep it a draft until the
|
||||
complete decomposition passes all acceptance gates below.
|
||||
|
||||
| Checkpoint | Responsibility | Deliverable and exit evidence |
|
||||
| --- | --- | --- |
|
||||
| N0 | Characterization | Public API/consumer, responsibility, state, lifecycle and network map; deterministic behavior tests; PR-overlap refresh; no extraction |
|
||||
| N1 | Recurrence domain | Only pure date/recurrence rules to `features/notes/domain/recurrence.js`; preserve old wrapper call contracts, time-read position and returned strings; new offline dependency registered |
|
||||
| N2 | Infrastructure | HTTP and storage adapters with exact request/error/key contracts; retain state ownership and backend authorization |
|
||||
| N3 | Application | Single state owner and CRUD/optimistic/undo workflows; UI/reminders call operations; no competing arrays or stores |
|
||||
| N4 | Reminders | Timer/notification/reminder orchestration through explicit ports; characterize startup, catch-up, deduplication, badge and background behavior |
|
||||
| N5 | UI substages | Bounded card/panel, editor/draft, checklist, drawing and mobile reviews within the same PR; explicit listener/observer disposal and the same application operations |
|
||||
| N6 | Compatibility and reference case study | Reduce coordinator; full API/consumer/lifecycle/offline comparison; retain legacy facade unless removal is proven safe; complete the final reference case study in the same PR |
|
||||
|
||||
Do not create the Notes worktree, branch or PR during F1. N5 remains several
|
||||
bounded internal reviews rather than a second monolith move. Every checkpoint
|
||||
and UI substage must have its own focused tests, review evidence, lessons,
|
||||
exceptions and a rollback plan. Record the validated revision or reproducible
|
||||
patch/snapshot, prior known-good checkpoint, exact test commands/results and
|
||||
how to restore its matching source/output/facade/precache set while preserving
|
||||
unrelated work. Checkpoint commits require the applicable maintainer authority;
|
||||
no checkpoint or commit is created by this planning document.
|
||||
|
||||
Advance only after the current checkpoint's required checks and review findings
|
||||
are resolved. A failed checkpoint returns to its prior validated state or receives
|
||||
a bounded correction on the same branch; it does not require a separate PR.
|
||||
If upstream changes require updating the baseline, update the same Notes branch,
|
||||
record that revision and rerun affected checkpoint and compatibility gates.
|
||||
|
||||
## Complete Notes PR acceptance gates
|
||||
|
||||
Before marking the single draft PR ready for review:
|
||||
|
||||
- Complete N0 through N6, including all N5 substages, with their tests, review
|
||||
receipts and reproducible checkpoint/rollback evidence.
|
||||
- Pass the required full Notes regression and compatibility checks on the final
|
||||
combined revision, including PR #6495 selection/context behavior, public APIs,
|
||||
module identities, single state ownership, storage formats, timers and teardown.
|
||||
- Pass source/output parity, LF attribute, architecture, import graph and exact
|
||||
offline manifest gates; verify current bootstrap/lazy behavior and relevant
|
||||
native/packaging contracts. Record platform limits and distinguish preserved
|
||||
offline module behavior from separately certified root offline reload.
|
||||
- Resolve required gate failures and review findings; document unrelated existing
|
||||
failures or coverage gaps explicitly rather than bypassing required checks.
|
||||
- Include the final reference case study in this PR: actual before/after APIs,
|
||||
dependency/state/lifecycle maps, stage decisions and lessons, validation recipes,
|
||||
temporary exceptions, known debt and tested rollback/compatibility procedures.
|
||||
|
||||
These are readiness gates for the complete PR, not separate stage merges.
|
||||
The receiving maintainer may choose smaller independent PRs for future frontend
|
||||
features; this one-PR delivery decision applies to the Notes reference program.
|
||||
|
||||
## N0 and N1 characterization requirements
|
||||
|
||||
Pin recurrence normalization for legacy bare repeat values and explicit values;
|
||||
none/unknown/malformed input; daily/weekly/monthly/yearly advancement; month ends,
|
||||
leap years, nth/last weekdays including absent fifth occurrences; overdue catch-up
|
||||
and the 5,000-step guard; future anchors; local serialization and preserved hours;
|
||||
DST gaps/overlaps under explicit time zones. `_advanceRecurring` currently reads
|
||||
`Date.now()` after its first step. Inject a clock without changing that ordering.
|
||||
Record the existing behavior of invalid dates rather than inventing improvements.
|
||||
|
||||
Characterize request error handling, optimistic rollback/undo, archive/delete,
|
||||
selection/filter/reset, ordering, uploads and notification permission errors.
|
||||
For drafts, preserve synchronous local backup before the 500 ms persistence
|
||||
timer, intentional empty text, checklist type fallback, serialized writes,
|
||||
failure recovery and refusal to clear a newer draft when an older save finishes.
|
||||
|
||||
Use stub clocks/ports and temporary storage for unit behavior; browser tests for
|
||||
public namespace evaluation, DOM lifecycle, selected context and actual offline
|
||||
loading. Run real modules through their output paths. Do not rewrite source-range
|
||||
tests wholesale; migrate each only with its responsible slice and equivalent
|
||||
behavioral assertions. Existing source-sensitive Notes autosave tests currently
|
||||
read `notes.js`, so extraction has an explicit test-maintenance dependency.
|
||||
|
||||
Before a slice, refresh #6585/#6647/#6652 backend behavior and #6470/#6695 shared
|
||||
UI/platform overlaps from the [assessment](assessment.md). Existing fixes may
|
||||
change characterization inputs, but this program does not merge or silently
|
||||
reimplement those PRs. The independent root-SW fix #6227 is required before a
|
||||
claim of full SPA offline reload readiness.
|
||||
|
||||
## H completion and stopping rule
|
||||
|
||||
The final reference case study is completed inside the Notes PR before it becomes
|
||||
ready for review. After that PR is integrated, finalize H with the integrated
|
||||
revision and checkpoint-to-integration receipts, outstanding dependencies and
|
||||
the recipient's independent reproduction. Have the receiving maintainer
|
||||
reproduce setup and validation independently and record that receipt. Transfer
|
||||
future feature ownership explicitly. Do not automatically begin Calendar,
|
||||
Documents, Email, Chat, Skills or Settings; the initiating architect continues
|
||||
with separately approved non-frontend monolith work.
|
||||
@@ -0,0 +1,453 @@
|
||||
# F1 implementation and review report
|
||||
|
||||
Date: 2026-10-13. Recommendation: ready for controlled incremental adoption after
|
||||
maintainer review, with the platform/offline limits below. The foundation proof
|
||||
is implemented and tested; Notes decomposition and the completed H handoff are
|
||||
planned only. No commit, push, merge, PR or issue operation was performed.
|
||||
|
||||
## Notes delivery documentation correction
|
||||
|
||||
The maintainer's final delivery decision is one comprehensive Notes draft PR
|
||||
targeting official `dev`, after the separate foundation-only F1 PR is integrated.
|
||||
N0 through N6 are internal engineering checkpoints in one Notes worktree and
|
||||
branch. The complete decomposition, regression tests, compatibility validation
|
||||
and final reference case study belong to that single PR; it stays a draft until
|
||||
the complete acceptance gates pass. Each stage retains its own test results,
|
||||
review receipts and reproducible rollback/checkpoint strategy, without requiring
|
||||
an independent GitHub PR. The receiving maintainer may choose smaller independent
|
||||
PRs for future frontend features.
|
||||
|
||||
This correction updates only `notes-roadmap.md`, `handbook.md` and this report.
|
||||
Implementation and test files retain their pre-correction bytes. All five
|
||||
foundation documents passed link, fence, whitespace, no-em-dash and delivery
|
||||
wording checks. `git diff --check` and the preserved-runtime diff check passed.
|
||||
A before/after snapshot confirmed exactly these three changed documents and
|
||||
15 unchanged existing F1 files. The implementation test results below remain
|
||||
the previous executed evidence; implementation tests were not rerun in this
|
||||
documentation-only pass.
|
||||
|
||||
## Independent review correction
|
||||
|
||||
The maintainer reports that the independent F1 review found no critical
|
||||
architectural defects. This pass preserves the reviewed native ESM architecture
|
||||
and scope. Its correction is to turn the documented LF checkout convention into
|
||||
a manifest-driven publisher/CI requirement. The full independent review text
|
||||
was not supplied; this report records the supplied finding and executed evidence.
|
||||
|
||||
The correction changes only `scripts/build_frontend.py`,
|
||||
`tests/test_frontend_build.py`, the ADR, the handbook and this report. The
|
||||
`.gitattributes` rules, architecture checker, CI workflow, manifest, dependencies
|
||||
and stateless source remain as reviewed. The full F1 inventory below still has
|
||||
18 files, including `.gitattributes`.
|
||||
|
||||
The publisher now evaluates both paths of every manifest entry through Git's
|
||||
actual attribute engine before parity evaluation or any deployment write. It
|
||||
requires `text: set` and `eol: lf` from applicable repository-owned attribute files,
|
||||
including nested overrides. A private temporary repository and isolated Git
|
||||
configuration prevent global attributes, local `.git/info/attributes`, templates
|
||||
or alternate Git directory settings from masking an omitted declaration. Paths
|
||||
are sent through NUL-delimited stdin, preserving spaces and using no shell/path
|
||||
quoting assumptions. The working repository's attributes, index and output are
|
||||
not changed by this check. Git is a publication/development prerequisite; the
|
||||
application does not invoke it to build or check frontend assets at startup.
|
||||
|
||||
The production integration diff is the new `check_lf_attributes(root, paths)`
|
||||
helper, four standard-library imports, this call, and updated CLI help:
|
||||
|
||||
```diff
|
||||
@@ synchronize
|
||||
if unlisted:
|
||||
raise ValueError(f"source modules missing from manifest: {sorted(map(str, unlisted))}")
|
||||
+ check_lf_attributes(root, sources | outputs)
|
||||
stale = []
|
||||
```
|
||||
|
||||
The tests add fixture LF declarations and 14 cases. Ten parameterized cases
|
||||
reject missing LF, CRLF, auto-text and binary-text rules for source/output paths
|
||||
in both publish and check modes, even when bytes already match. The other four
|
||||
cover a future manifest pair failing before any output is published and passing
|
||||
after its LF declaration; nested rules and a spaced path; global/local settings
|
||||
failing to mask an omitted repository rule; and clear failure without development
|
||||
Git. Existing publication, ownership, confinement, parity and runtime tests remain.
|
||||
|
||||
## Exact attributes diff and checkout evidence
|
||||
|
||||
`git diff -- .gitattributes` is unchanged from the reviewed F1 diff:
|
||||
|
||||
```diff
|
||||
diff --git a/.gitattributes b/.gitattributes
|
||||
index 8681aee1..dd49c4a0 100644
|
||||
--- a/.gitattributes
|
||||
+++ b/.gitattributes
|
||||
@@ -10,6 +10,10 @@
|
||||
entrypoint.sh text eol=lf
|
||||
docker/entrypoint.sh text eol=lf
|
||||
|
||||
+# Maintained frontend modules and this lane's byte-identical deployment output.
|
||||
+frontend/src/** text eol=lf
|
||||
+static/js/actionMenuOrder.js text eol=lf
|
||||
+
|
||||
# Windows-native scripts stay CRLF.
|
||||
*.ps1 text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
```
|
||||
|
||||
Exact command and results:
|
||||
|
||||
```text
|
||||
$ git check-attr text eol -- frontend/src/shared/actionMenuOrder.js static/js/actionMenuOrder.js
|
||||
frontend/src/shared/actionMenuOrder.js: text: set
|
||||
frontend/src/shared/actionMenuOrder.js: eol: lf
|
||||
static/js/actionMenuOrder.js: text: set
|
||||
static/js/actionMenuOrder.js: eol: lf
|
||||
```
|
||||
|
||||
The sampled legacy contracts were also inspected:
|
||||
|
||||
| Path | text | eol |
|
||||
| --- | --- | --- |
|
||||
| `static/js/notes.js` | auto | unspecified |
|
||||
| `static/index.html` | auto | unspecified |
|
||||
| `launch-windows.ps1` | set | crlf |
|
||||
| `start-macos.sh` | set | lf |
|
||||
|
||||
Beyond samples, all 2,479 unrelated tracked paths were compared against HEAD for
|
||||
both attributes and matched. The current Git 2.53.0 supports the diagnostic
|
||||
`--source=HEAD` option; the publisher uses only the longstanding plain
|
||||
`check-attr --stdin` interface, so it does not depend on that newer option.
|
||||
The read-only whole-tree comparison command was:
|
||||
|
||||
```sh
|
||||
python3 - <<'PY'
|
||||
import subprocess
|
||||
paths = subprocess.check_output(['git', 'ls-files', '-z'])
|
||||
def attributes(source):
|
||||
result = subprocess.run(
|
||||
['git', 'check-attr', *source, '-z', '--stdin', 'text', 'eol'],
|
||||
input=paths, capture_output=True, check=True,
|
||||
)
|
||||
fields = result.stdout.decode().split('\0')[:-1]
|
||||
return {(fields[i], fields[i + 1]): fields[i + 2]
|
||||
for i in range(0, len(fields), 3)}
|
||||
before, after = attributes(['--source=HEAD']), attributes([])
|
||||
owned = lambda p: p.startswith('frontend/src/') or p == 'static/js/actionMenuOrder.js'
|
||||
changes = [(p, a, before[(p, a)], value) for (p, a), value in after.items()
|
||||
if not owned(p) and before[(p, a)] != value]
|
||||
assert not changes, changes
|
||||
print(len({p for p, a in after if not owned(p)}), 'unrelated tracked paths unchanged')
|
||||
PY
|
||||
```
|
||||
|
||||
## Ownership enforcement after correction
|
||||
|
||||
| Contract | Enforcement and CI receipt |
|
||||
| --- | --- |
|
||||
| Canonical, contained source/output paths and unique ownership | Publisher validates the whole manifest before writing; `python-syntax` runs its `--check` |
|
||||
| Every maintained JS source is registered | Publisher rejects unlisted source; duplicate sources/outputs also fail |
|
||||
| Reproducible LF checkout of both mapped paths | Publisher queries isolated repository-owned attributes, even for already matching bytes; the same CI `--check` now enforces it |
|
||||
| Committed output equals maintained source | Publisher checks byte parity without rebuilding in CI; normal publication writes only stale owned outputs |
|
||||
| Feature API/layer direction, no new cycles, stable relative resolution and maintained identities | Existing architecture checker and Node self-tests in `node-syntax`; no checker changes needed |
|
||||
| Explicit exact-URL offline coverage | Architecture checker parses the existing SW arrays; real offline browser proof remains green |
|
||||
| Legacy runtime graph/URL identity and behavior | Existing focused pytest guards and the full CI pytest jobs remain in place |
|
||||
|
||||
These gates enforce the documented maintained-JS contract together. They do not
|
||||
retroactively impose source ownership on all legacy static files, clean retired
|
||||
outputs or prove semantic state/lifecycle correctness. Those existing limits and
|
||||
the independent packaging/offline limitations below remain unchanged.
|
||||
|
||||
## Final correction validation
|
||||
|
||||
The full focused pytest command printed below was rerun with the same interpreter
|
||||
and all listed files: **193 passed, 1 skipped, 1 existing SQLAlchemy warning in
|
||||
12.33 s**. It includes all 27 publisher tests and the isolated native startup,
|
||||
static traversal and no-Node distribution probe. The new 14 tests account for
|
||||
the increase from the initial F1 run's 179 passes. No test failed in this pass.
|
||||
|
||||
| Correction check | Actual result |
|
||||
| --- | --- |
|
||||
| Combined focused pytest command below | 193 passed, 1 unavailable-image skip |
|
||||
| `node --test tests/frontendArchitecture.test.mjs` | 10 passed |
|
||||
| Notes oracle/autosave/selected-context command below | 11 passed |
|
||||
| `python3 scripts/build_frontend.py` | Passed, zero output changes, attributes enforced |
|
||||
| `python3 scripts/build_frontend.py --check` | Passed, attributes and byte parity enforced |
|
||||
| `node scripts/check_frontend.mjs` | Passed, one maintained module |
|
||||
| Helper SHA-256 and `git check-attr` | Identical source/output hash; both text=set, eol=lf |
|
||||
| All unrelated tracked attributes versus HEAD | 2,479 paths unchanged |
|
||||
| `git diff --check` and preserved-runtime command below | Passed, no runtime/backend/packaging diff |
|
||||
| `python -m compileall -q scripts/build_frontend.py tests/test_frontend_build.py` | Passed using the recorded virtualenv interpreter |
|
||||
| Isolated Docker runtime command below | Passed, networking disabled; no source tree, node_modules or Node on PATH |
|
||||
| Complete inventory, whitespace and documentation links | All 18 changed files matched the inventory; checks passed |
|
||||
|
||||
The one skip remains the existing test requiring `odysseus-odysseus:latest`.
|
||||
No new skip or waiver was introduced. Windows/macOS executable builds, a fresh
|
||||
full Dockerfile build, the full pytest suite, Firefox/WebKit and CI's exact
|
||||
Python 3.11/Node 20 versions remain unexecuted locally. Native Git semantics,
|
||||
nested overrides, paths with spaces and ignored `core.autocrlf`/global attribute
|
||||
settings are covered by executed Linux tests; actual Windows execution remains a
|
||||
platform-owner check. The existing `/static/` worker scope still prevents a claim
|
||||
of full root offline reload readiness. No service-worker scope change is included.
|
||||
|
||||
The earlier local ChromaDB probe incident remains recorded under failures below.
|
||||
All runtime checks in this correction pass used the isolated distribution probe
|
||||
with reserved non-listening Chroma port and disabled warmups; Docker additionally
|
||||
had networking disabled. This pass performed no new unisolated ChromaDB probe and
|
||||
no attempt to restore or alter the existing local service's tool index.
|
||||
|
||||
## Reviewer-ready PR summary
|
||||
|
||||
Suggested title: `Establish frontend source ownership and native ESM deployment contracts`.
|
||||
|
||||
Maintain a stateless helper under `frontend/src/` while publishing identical bytes
|
||||
at its existing static URL. Add manifest-owned publication, repository-owned LF
|
||||
attribute and byte-parity checks, parsed dependency/API/identity/offline gates,
|
||||
and a self-contained architecture handbook with the Notes decomposition roadmap.
|
||||
Startup and existing feature behavior retain their current runtime contracts.
|
||||
|
||||
Validation: 193 focused Python tests passed with one existing Docker-image skip;
|
||||
10 architecture and 11 Notes compatibility tests passed; source/output parity,
|
||||
LF gates, preserved-runtime diff and isolated native/Docker runtime proofs passed.
|
||||
Desktop executable builds and full root offline reload remain explicit limits.
|
||||
All 18 files are inventoried below. The working diff is ready for review and is
|
||||
uncommitted; commit, push and PR creation require separate authorization.
|
||||
|
||||
## Verified repository state
|
||||
|
||||
Repository: `odysseus-dev/odysseus`. Branch:
|
||||
`refactor/frontend-architecture-foundation`. Worktree:
|
||||
`/home/alteixeira20/Projects/Odysseus/worktrees/architecture/frontend-foundation`.
|
||||
Initial worktree was clean. HEAD and local official `upstream/dev` are
|
||||
`8feb50e89468235cd3e0986da80edbd3acaf2c40`. The live official GitHub `dev` SHA
|
||||
matched at both initial and final verification. This is PR #6495's merge commit.
|
||||
The `origin` remote is the maintainer fork, not the integration target.
|
||||
|
||||
Final changes are uncommitted F1 files only. Runtime JavaScript, Notes, HTML,
|
||||
SW, backend, Dockerfile and desktop startup/packaging implementations have no
|
||||
diff. The stateless source and existing deployed helper are both 1,688 bytes,
|
||||
SHA-256 `e17baec5d6ac381ce6234ab6f028a8208487280dd07d6950a3469f8488809684`.
|
||||
The final publisher run reported zero changed output modules.
|
||||
|
||||
## Decisions and scope
|
||||
|
||||
The [ADR](ADR-001-source-and-deployment.md) compares two executed approaches:
|
||||
controlled native ESM copying and esbuild 0.25.12 ESM compilation/bundling.
|
||||
Native byte copying wins on existing URL/module/cache compatibility and absence
|
||||
of runtime tooling. Commit explicit output beside maintained source, publish
|
||||
only manifest-owned modules and enforce parity in CI. Python startup never builds.
|
||||
|
||||
The [handbook](handbook.md) defines feature public indexes, responsibility layers,
|
||||
state/lifecycle ownership, cross-feature ports/events, shared-code limits, legacy
|
||||
coexistence, module creation, validation, rollback and handoff contracts.
|
||||
The [assessment](assessment.md) records graph/bootstrap/state/storage/security,
|
||||
packaging assumptions and current open-PR overlaps. The
|
||||
[Notes roadmap](notes-roadmap.md) defines N0 through N6 as internal checkpoints
|
||||
for one comprehensive Notes draft PR, with the final reference case study in
|
||||
that PR and H recipient handoff after integration. None is implemented in F1.
|
||||
There is one maintained stateless leaf and zero legacy-import
|
||||
exceptions, with no empty feature scaffolding.
|
||||
|
||||
Acorn 8.19.0 is the sole new, exact-pinned development dependency, used to parse
|
||||
architecture edges accurately. It is not loaded or distributed as runtime JS.
|
||||
esbuild was a pinned one-off spike and is not a project dependency. Existing
|
||||
frameworks, application entry points and backend contracts are unchanged.
|
||||
|
||||
## Exact changed files
|
||||
|
||||
| File | Change |
|
||||
| --- | --- |
|
||||
| `.gitattributes` | LF checkout for maintained source and the registered deployed proof |
|
||||
| `.github/workflows/ci.yml` | Parity check; locked parser install; source syntax and architecture self-tests |
|
||||
| `package.json` | Exact Acorn development dependency |
|
||||
| `package-lock.json` | Acorn lock/integrity entry |
|
||||
| `frontend/modules.json` | Explicit source/deployment ownership mapping |
|
||||
| `frontend/src/package.json` | Native ESM interpretation for source tests, no dependencies |
|
||||
| `frontend/src/shared/actionMenuOrder.js` | Authoritative stateless source, copied verbatim from the existing helper |
|
||||
| `scripts/build_frontend.py` | Validated source publisher with manifest-driven, repository-owned LF enforcement and non-mutating parity check |
|
||||
| `scripts/check_frontend.mjs` | Parsed import/layer/API/cycle/identity/precache guards and graph inventory |
|
||||
| `scripts/verify_frontend_runtime.py` | Isolated current-code distribution/runtime compatibility probe |
|
||||
| `tests/frontendArchitecture.test.mjs` | Behavioral API equivalence and positive/negative architecture gates |
|
||||
| `tests/test_frontend_build.py` | Publication/ownership/drift/runtime coverage plus positive and negative Git attribute enforcement tests |
|
||||
| `tests/test_frontend_foundation_offline_js.py` | Real SW precache, offline first evaluation, canonical namespace identity and lazy registry proof |
|
||||
| `docs/frontend-architecture/ADR-001-source-and-deployment.md` | Decision, alternatives and distribution/rollback contracts |
|
||||
| `docs/frontend-architecture/assessment.md` | Evidence-backed architecture and PR-overlap inventory |
|
||||
| `docs/frontend-architecture/handbook.md` | Permanent foundation and maintainer continuation methodology |
|
||||
| `docs/frontend-architecture/notes-roadmap.md` | Reference decomposition and final handoff plan |
|
||||
| `docs/frontend-architecture/validation.md` | This implementation/review/validation report |
|
||||
|
||||
## Initial F1 validation before the review correction
|
||||
|
||||
Environment: Linux; native Python 3.14.4; pytest 9.1.1; FastAPI 0.143.0;
|
||||
Starlette 1.8.0; Node 22.23.1; Playwright 1.62.1 with installed Chromium.
|
||||
CI remains Python 3.11 and Node 20; that exact interpreter pair was not executed
|
||||
locally. Use the repository virtualenv, not the system Python missing dependencies.
|
||||
The interpreter used here was
|
||||
`/home/alteixeira20/.venvs/odysseus-pr-6495/bin/python`.
|
||||
|
||||
The historical counts below are coordinator-executed checks in this worktree, excluding
|
||||
delegated claims and earlier repeated subsets. Delegation was discontinued on
|
||||
user instruction; no delegated implementation was integrated.
|
||||
|
||||
| Check | Actual result |
|
||||
| --- | --- |
|
||||
| Read-only baseline: graph, identity, helper, loader, MIME, nonce, runtime paths | 54 passed, one existing SQLAlchemy deprecation warning |
|
||||
| Final combined focused pytest command below | 179 passed, 1 skipped, one existing SQLAlchemy warning, 12.62 s |
|
||||
| Final `pytest -q -rs tests/test_frontend_build.py` review rerun | 13 passed, including native startup and encoded static traversal rejection |
|
||||
| `node --test tests/frontendArchitecture.test.mjs` | 10 passed, no skips or failures; rerun after final gate review |
|
||||
| Notes oracle/autosave/selected-context Node command below | 11 passed, no skips or failures |
|
||||
| `python3 scripts/build_frontend.py` and `--check` | Zero output changes; byte parity passed |
|
||||
| `node scripts/check_frontend.mjs` | Passed, one maintained module |
|
||||
| `node scripts/check_frontend.mjs --inventory` | 230 files, 707 static edges, 108 lazy literal edges, no missing targets, three existing static cyclic components |
|
||||
| `npm ci --ignore-scripts --no-audit --no-fund` | Locked development dependency installation succeeded |
|
||||
| Native `scripts/verify_frontend_runtime.py` | Real FastAPI lifespan and shell/static assertions passed without maintained source, node_modules or Node on PATH |
|
||||
| Docker runtime probe below | Same current-code assertions passed with networking disabled and source mount read-only |
|
||||
| esbuild spike | Two identical 1,554-byte bundle outputs; executed exports/icon/ordering equivalence passed |
|
||||
| JS syntax checks and Python compileall below | Passed |
|
||||
| `git diff --check`, preserved-scope diff check, hash/LF checks | Passed; no runtime/backend/packaging source diff |
|
||||
| Foundation documentation links, trailing whitespace and em-dash checks | All five files passed |
|
||||
|
||||
The skipped test is
|
||||
`tests/test_docker_devops_hardening.py:187`, which requires the unavailable
|
||||
`odysseus-odysseus:latest` image. It was not relabeled or bypassed. F1's separate
|
||||
Docker runtime probe used the available `odysseus-maintainer-preview-odysseus:latest`,
|
||||
image ID `sha256:cc2d47e2327d573af01c6b027f23d2ab0f2ee9b85d658e9eb8065bd02b9c3515`,
|
||||
with Python 3.14.7, FastAPI 0.141.1 and Starlette 1.6.0. This proves compatibility
|
||||
of current candidate code/assets with that image's runtime dependencies, not a
|
||||
fresh build of the full repository Dockerfile or a deployment.
|
||||
|
||||
Reproduce the final focused command with the actual tested interpreter:
|
||||
|
||||
```sh
|
||||
/home/alteixeira20/.venvs/odysseus-pr-6495/bin/python -m pytest -q -rs \
|
||||
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_action_menu_order.py tests/test_panel_loader_js.py \
|
||||
tests/test_app_static_mime.py tests/test_serve_html_with_nonce.py \
|
||||
tests/test_runtime_paths.py tests/test_ci_authoritative_validation.py \
|
||||
tests/test_selected_notes_context.py tests/test_email_library_module_graph_js.py \
|
||||
tests/test_settings_module_import_paths.py tests/test_app_config_shared_fetch_js.py \
|
||||
tests/test_markdown_lazy_lib_loading_js.py tests/test_startup_shell_js.py \
|
||||
tests/test_static_stylesheet_manifest.py tests/test_notes_dom_xss_helpers.py \
|
||||
tests/test_notes_reminder_temporal_redos.py tests/test_notes_sidebar_new_note.py \
|
||||
tests/test_notes_mobile_checklist_toggle_static.py \
|
||||
tests/test_notes_document_mutual_minimize.py tests/test_docker_devops_hardening.py
|
||||
|
||||
node --test tests/frontendArchitecture.test.mjs
|
||||
ENDPOINT_URL=http://127.0.0.1:1 node --test \
|
||||
tests/noteTestOracle.test.mjs tests/notesDraftAutosave.test.mjs \
|
||||
tests/selectedNotesContext.test.mjs
|
||||
|
||||
python3 scripts/build_frontend.py --check
|
||||
node scripts/check_frontend.mjs
|
||||
/home/alteixeira20/.venvs/odysseus-pr-6495/bin/python scripts/verify_frontend_runtime.py
|
||||
|
||||
docker run --rm --network none \
|
||||
--mount type=bind,src=/home/alteixeira20/Projects/Odysseus/worktrees/architecture/frontend-foundation,dst=/candidate,readonly \
|
||||
--workdir /candidate --entrypoint python \
|
||||
odysseus-maintainer-preview-odysseus:latest scripts/verify_frontend_runtime.py
|
||||
```
|
||||
|
||||
`ENDPOINT_URL` satisfies the existing oracle's import-time configuration requirement.
|
||||
Its unit-test imports exercise pure exported functions; its network-driving main
|
||||
is guarded by the executable-module check and does not run. The closed loopback
|
||||
address is not a live model endpoint. No oracle implementation was changed.
|
||||
|
||||
Syntax commands executed:
|
||||
|
||||
```sh
|
||||
bash -c 'shopt -s globstar nullglob; for f in static/app.js static/js/**/*.js frontend/src/**/*.js scripts/check_frontend.mjs tests/frontendArchitecture.test.mjs; do node --check "$f" || exit; done'
|
||||
/home/alteixeira20/.venvs/odysseus-pr-6495/bin/python -m compileall -q app.py core routes src services scripts tests
|
||||
git diff --check
|
||||
git diff --exit-code -- static app.py Dockerfile .dockerignore Odysseus.spec build-macos-app.sh build-windows-portable.ps1 launcher.py core routes src services
|
||||
git check-attr text eol -- frontend/src/shared/actionMenuOrder.js static/js/actionMenuOrder.js
|
||||
sha256sum frontend/src/shared/actionMenuOrder.js static/js/actionMenuOrder.js
|
||||
```
|
||||
|
||||
Spike compiler invocation, executed twice with equality and Node import assertions:
|
||||
|
||||
```sh
|
||||
npx --yes esbuild@0.25.12 frontend/src/shared/actionMenuOrder.js \
|
||||
--bundle --format=esm --target=es2022 --platform=browser --log-level=error
|
||||
```
|
||||
|
||||
The clean publication proof uses temporary roots in `test_frontend_build.py`,
|
||||
including an initially absent output tree. Real-checkout publication is idempotent.
|
||||
No emitted JS bytes, URLs, boot scripts or cache manifests changed in this lane.
|
||||
|
||||
## Failures encountered and their resolution
|
||||
|
||||
- An early architecture self-test expected an identity diagnostic but got an
|
||||
unresolved source path for a query-bearing relative import. The checker now
|
||||
rejects alternate identity before resolving that source path. All final tests
|
||||
pass; no test requirement was weakened.
|
||||
- The initial Notes oracle command failed during import because `ENDPOINT_URL`
|
||||
was missing. Inspection established that the unit-test path never runs its
|
||||
endpoint-driving main. The explicit closed-address configuration above passed
|
||||
all 11 tests. This prerequisite is recorded for N0 rather than hidden.
|
||||
- The first isolated distribution fixture omitted the existing `companion/`
|
||||
package, so both probes failed with `ModuleNotFoundError`. The fixture now
|
||||
includes that required runtime directory; neither application nor packaging
|
||||
implementation was modified to make the tests pass.
|
||||
- The first exploratory native startup check connected to the existing local
|
||||
ChromaDB and refreshed the built-in tool index. That was unintended. Subsequent
|
||||
probes use a private distribution/data directory, a reserved non-listening
|
||||
Chroma port, disabled existing warmup options and no Node on PATH. Docker also
|
||||
disables networking. No attempt was made to overwrite or restore that service's
|
||||
data; the earlier unisolated probe is not the reproducible validation recipe.
|
||||
|
||||
## Remaining risks and limits
|
||||
|
||||
Root offline reload is not certified: existing SW scope is `/static/`, and open
|
||||
[#6227](https://github.com/odysseus-dev/odysseus/pull/6227) proposes the independent
|
||||
scope/header correction. F1 preserves and tests actual offline module behavior
|
||||
at the current scope. No first-use offline guarantee is claimed for optional
|
||||
CDN libraries, Mermaid or server APIs.
|
||||
|
||||
Windows/macOS packaged executables, a fresh full Dockerfile build, the full pytest
|
||||
suite, Firefox/WebKit offline behavior and CI's exact Python 3.11/Node 20 versions
|
||||
were not executed here. Existing packaging paths are inspected and unchanged;
|
||||
platform owners should run release validation before broader certification.
|
||||
The unavailable-image test remains a coverage gap. Legacy source still has
|
||||
cross-feature coupling, global side effects and static cycles. New boundaries
|
||||
are enforced on maintained source, not retrospectively on the entire legacy tree.
|
||||
|
||||
The publisher intentionally does not clean retired outputs or provide atomic
|
||||
multi-file deployment. Review full source/output/facade/manifest changes and
|
||||
ship a coherent artifact. Domain syntax checks cannot prove all semantic purity
|
||||
or disposal; behavioral characterization remains required. Reconcile the package
|
||||
lock with #6627 and refresh all PR overlaps before integration.
|
||||
|
||||
## Reviewer checklist
|
||||
|
||||
- Verify the base contains #6495 and the official integration target is dev.
|
||||
- Confirm the deployed helper hash and runtime-scope diff are unchanged.
|
||||
- Review the layer matrix, public API rules, single-state ownership and zero
|
||||
current legacy exceptions; verify negative tests actually reject violations.
|
||||
- Review the manifest mapping, byte-parity/LF policy, exact offline precache and
|
||||
source/output relative-resolution guard; verify missing or overridden LF
|
||||
declarations fail publication and CI even when output bytes already match.
|
||||
- Reproduce the focused tests and inspect the skipped-image prerequisite.
|
||||
- Confirm no frontend compiler/runtime dependency is required at startup and
|
||||
inspect the isolated Python/Docker probe's limits.
|
||||
- Review overlap with #6470/#6695/#6227/#6627 and the Notes backend follow-ups.
|
||||
- Treat the ADR as awaiting adoption review, and the Notes/H documents as plans.
|
||||
- Authorize any commit/push/PR action separately. Do not begin Notes on this branch.
|
||||
|
||||
## Required next reviews and continuation
|
||||
|
||||
1. Review this F1 working diff. On explicit authorization, commit and submit only
|
||||
the foundation-only F1 PR to official dev using the normal maintainer workflow.
|
||||
2. Coordinate the existing #6227 offline fix and platform release validation as
|
||||
separate work. Do not bundle that behavioral change into F1.
|
||||
3. After F1 integration and Notes implementation authorization, create one Notes
|
||||
worktree and branch from the latest official dev, preserving any subsequently
|
||||
merged Notes changes. Use one comprehensive draft PR targeting official dev.
|
||||
4. Complete N0 through N6 from the [Notes roadmap](notes-roadmap.md) on that same
|
||||
branch, recording tests, review and rollback evidence at each checkpoint. Include
|
||||
the final reference case study in the same PR and keep it a draft until the full
|
||||
decomposition and regression/compatibility acceptance gates pass. Recurrence
|
||||
extraction follows characterization as an internal stage, not another PR.
|
||||
5. Complete H only after Notes integration and recipient reproduction. Transfer
|
||||
future frontend work to the designated maintainer and stop this program.
|
||||
|
||||
Another maintainer can start at the handbook, run the documented source/parity,
|
||||
architecture, runtime and behavior checks, inspect this report and select the
|
||||
next authorized slice without relying on unwritten architecture decisions.
|
||||
Reference in New Issue
Block a user