Development
The supported reproducible toolchain is Nix on x86_64 Linux. Node 24,
TypeScript, Chromium, Just, formatters, linters, and the shared MkDocs
environment are pinned through flake.lock. No npm installation is needed
inside the Nix shell; the TypeScript tool is supplied by Nix.
package-lock.json remains available for manual npm development.
nix develop
just ci
just serve
just serve opens the app on http://localhost:8000. Credentials made there
are for rehearsal and cannot unlock production boxes. just serve-docs uses
port 8001.
nix flake check --no-eval-cache
nix develop --quiet -c just ci
nix build .#site
nix develop --quiet -c bash scripts/smoke-site.sh result
Flake checks actually execute their matching apps in the sandbox: typecheck, unit, browser, format-check, lint, and docs-check. CI also enters the development shell and runs the full local command. Chromium is mandatory: absent browser coverage is a failure, not a passing skip. Browser tests use a virtual PRF authenticator and a fake GitHub API; test real hardware separately.
Use just format and just format-check for Nix and repository
configuration/docs. Existing compact JavaScript style is preserved; JSDoc type
checks cover the app and its modules listed in tsconfig.json. Workflow lint
and shellcheck run through just lint. The app's dependency boundary remains
checked too.
Read the
contribution guide
and project constitution before changing behavior. Specifications for repository
setup live in specs/017-repository-quality/.
System design
The architecture pages preserve their explicit pre-feature source snapshot. Expressive records are now implemented in the modules described above and in the feature models. Their twelve abstract proofs and browser regressions do not complete the separate audited model and simulation loop proposed by those pages.
Start with the architecture baseline and design work plan. Update them when a module boundary, key lifecycle, persistent format, or trust boundary changes. Keep proposed feature models separate until implementation evidence supports moving them into the baseline. The system-design skill plan prepares a first slice using the existing shared workflow. The formal model, proofs and simulation have not started.
Design diagrams are rendered locally from docs/diagrams/*.mmd using the
Mermaid CLI pinned by this repository’s flake.lock:
nix shell --impure --expr 'let p = (builtins.getFlake (toString ./.)).inputs.nixpkgs.legacyPackages.x86_64-linux; in [ p.mermaid-cli p.python3 ]' -c python3 scripts/render-docs-diagrams.py
Commit the sources, SVGs and generated manifest together. The strict docs build rejects stale diagram assets and stale speech companions. Presentation checks currently cover the home, development and architecture pages; this does not certify the legacy documentation. Diagrams need no runtime CDN renderer.
Spec-driven changes
Constitution 1.1.0 is the governing baseline for new feature work. Write the
user-visible specification and resolve unclear requirements before designing
implementation. During planning, write modules-model.md first, then
data-model.md and functions-model.md, covering only changed boundaries.
Generate acceptance-linked tasks only after these contracts agree.
Keep each module focused: pure record/validation logic must not import DOM, storage, clipboard, or networking. UI composition and browser effects have separate owners. New modules participate in the relevant type and test gates. Record changes require legacy fixtures and lossless round-trip tests; field UI changes require safe-link, copy/reveal, lock/reset, and accessibility coverage. The templates contain explicit constitution checks rather than optional test placeholders.
The expressive-record specification and technical plan live in
specs/024-expressive-records/.
The design keeps record/domain logic, encrypted formats, persistence, UI, and
browser effects in separate owners. It requires migration backups and a shared
save/session boundary shared by record, key and token writes. Pull and lock
invalidate pending work; exact-source comparison inside the IndexedDB
transaction refuses stale writes from another tab. The broader audit issue
remains open.
Contributors can exercise the developing storage/session boundary through
just browser. Its synthetic legacy fixtures retain complete notes and token
records; the tests use real IndexedDB for migration backups, source conflicts,
failed writes and late asynchronous completions. Authentication in those
controller cases is injected, while app scenarios use Chromium's virtual
authenticator. The app-level Pull regression failed against the old writer and
passes through the new controller. These checks do not establish real-hardware
interoperability or cryptographic security.