GoingNinja Manual Knowledge Wiki logo
GoingNinja Manual Knowledge Wiki Lean MVP bootstrap documentation // Felix Rascher (WIP)

Recent Writebacks

System Audits Need One Staged Workspace

If a multi-repo audit points Claude or Gemini at a sprawling parent directory, a symlink chain, or a mutable live tree, the resulting failure is not "tool bad luck." It is a platform bug.

The stable rule is:

  • freeze the snapshot
  • copy the exact repos or paths into one deterministic audit workspace
  • record that staged tree in AUDIT_WORKSPACE.json
  • run the external system lane only against that staged workspace

This rule exists because headless reviewer CLIs often apply path safety and workspace boundaries that differ from an interactive human shell. The platform must solve that once instead of rediscovering it in every proof case.

A Strong Verdict Counts Only On A Proven Audit Surface

If an earlier audit says strong, but the audit lane later breaks because the workspace boundary, CI writer path, or snapshot discipline was incomplete, the earlier strong was not closure-complete.

The stable rule is:

  • treat the audit execution surface itself as part of the contract
  • prove that the lane can run deterministically
  • only then trust strong as a real closure signal

strong is therefore not just a statement about content or code. It is also a statement about whether the audit path itself was mechanically valid.

Tool Roles Must Separate The Role From The Current Tool

The platform should describe:

  • the role
  • the current proof tool that fills that role
  • and the exact point where vendor support ends and platform convention begins

If those layers blur together, a newcomer cannot tell whether the system depends on one private tool or on a reusable role contract.

The stable documentation rule is:

  • describe the builder lane as a role first
  • then name the current proof surface only as an example
  • and keep vendor claims tied to public documented surfaces

Provider Baselines Need One Canonical Owner

Provider setup belongs to one canonical page. Other pages may depend on that setup, but they should link back to the owner instead of restating the same provider list with slightly different wording.

That keeps the manual:

  • lighter to read
  • easier to update
  • and less likely to drift across setup, planning, and proof pages

It exists so the same failure class does not return under a different filename, surface, or repo.

Wiki Assistants Need One Live Model And One Trust Pattern

The first public assistant cut should not start with model choice theater. If only one provider is truly verified, expose one live model and make the trust pattern explicit.

The stable rule is:

  • one live model in the first release
  • one clear scope statement above the conversation
  • one explicit non-goal statement for off-topic questions
  • visible source links under every grounded answer
  • starter prompts for first use and follow-up prompts after an answer
  • modal assistants must respect dialog focus rules instead of acting like decorative overlays

If the public product positioning carries a regional claim, the live assistant provider should support that claim clearly enough that the UI does not feel contradictory.

That keeps the assistant teachable for first-time readers and avoids a false impression of platform maturity.

Assistant Embeds Should Use Familiar Sheet And Chat Patterns

The assistant should not look like a second homepage inside a modal. Readers already know two patterns:

  • a side sheet on desktop
  • a bottom sheet on mobile
  • one compact assistant header
  • one short onboarding card
  • one conversation area
  • one fixed composer at the bottom

The stable rule is:

  • the wiki owns the launch button and the sheet shell
  • the assistant owns the chat surface inside that shell
  • the first viewport must explain scope, non-goals, and source discipline clearly
  • the embedded assistant must not duplicate full page marketing or page-local layout ideas

This keeps the assistant recognizable as a tool, not a second website hidden inside the website.

Public Request Forms Need A CSP That Allows Their Own Submit Path

The rascher.online worker can accept a valid POST and still ship a broken browser flow if the shared page CSP says form-action 'none'.

The stable rule is:

  • public request pages may stay tight on scripts and frames
  • but the root CSP must allow form-action 'self' when the surface owns a real HTML form
  • a successful curl POST is not enough proof; the browser-facing CSP must permit the same action

Otherwise the page looks finished while the real button is dead.

Approval Is Only Real When Group Membership Changes Too

Reader approval does not end at the registry row. If the D1 state says approved but the email is not added to the correct Cloudflare Access group, the approval is mechanically incomplete.

The stable rule is:

  • approve updates the review registry
  • approve also adds the email to the correct Access group
  • mark-deleted removes the email from that group again
  • protected Access applications must point at those groups instead of direct email lists

That is the only way the request flow, review flow, and actual protected surface stay one system instead of three drifting systems.

Protected Root Surfaces Should Validate The Access JWT, Not Just Trust A Header

Cloudflare Access forwards convenient identity headers, but protected application routes should still validate the Access JWT against the real audience.

The stable rule is:

  • protect the route with Cloudflare Access
  • validate CF-Access-Jwt-Assertion
  • bind the route to the specific app audience instead of trusting a copied header value alone

That keeps account and admin actions inside the real protected session boundary.

Protected Account Actions Must Stay Inside The Protected Account Surface

Deletion and scope visibility do not belong on the public root entry page.

The stable rule is:

  • public root may show login and request-access entry actions
  • request flow may ask which protected area is needed
  • approved users manage deletion and visibility from one protected account surface
  • admin review belongs in one protected admin surface, not in copied ad-hoc pages

That keeps the public entry quiet and the destructive actions inside the authenticated boundary.

Mobile Sheets Must Be Hidden By Default Until The Open State Exists

A modal sheet is not "closed" just because JavaScript intends to close it later. If a shared selector makes the shell visible before [open] exists, the page is already broken on smaller viewports.

The stable rule is:

  • shared dialog shells default to display: none
  • only the real open state may switch them to layout display
  • mobile media queries must not override a closed dialog into visibility

Otherwise a second assistant or sheet appears permanently open and blocks the page behind it.

How To Read This Page

The numbered lessons cover three recurring groups:

  • shared contract and build rules: 1-6, 14-26, 30-32
  • audit and review process: 7-13, 27-29, 33
  • product genesis, proof, and platform teaching: 34-40

The global rule is:

  • if a lesson is strong enough to stop work, it must move into a template, check, or shared contract
  • if a lesson is still only explanatory, it must not be described as a hard mechanical guarantee

1. Contracts Must Have One Owner

The main source of avoidable complexity was duplicated truth.

The fix is simple:

  • one owner for routing
  • one owner for page metadata
  • one owner for CSP
  • one owner for shared shell and spacing
  • one owner for brand assets

If two sibling files carry the same contract, drift has already started.

2. Shared UI Must Live Once

Landing pages, manuals, and workers may extend the same visual system, but they must not fork it casually.

The reusable contract now lives in shared UI primitives:

  • tokens
  • styles
  • shared assets
  • shared shell components

That is the only reliable way to keep typography, spacing, colors, SVGs, and framing identical across surfaces.

3. Generated Output Is Not Source

Several earlier problems came from fixing generated files instead of the real source that produces them.

The stable rule is:

  • edit source under versioned repo paths
  • regenerate the built site
  • never treat site/ output as hand-authored logic

4. Surface Splits Beat Monoliths

The code became cleaner only after splitting by runtime surface:

  • shared core
  • manual surface
  • root landing surface

That split is leaner than one giant file because each surface can import the contracts it actually uses.

5. Security Must Be Shared, But Tight

Security headers must be shared from one contract, not repeated across build scripts and workers.

At the same time, permissions should stay narrow:

  • pin external browser scripts with the real runtime primitive, which is SRI in the HTML tag
  • let CSP allow the trusted origin instead of pretending the CSP hash is the execution pin
  • derive font CSP origins from the same source as font preconnect links
  • keep SVG asset CSP stricter than page CSP
  • fail unknown routes with 404

6. Equivalent Paths Need Equivalent Validation

Several real bugs came from validating one case but not its sibling:

  • relative asset links were checked while absolute asset links were trusted
  • registry SVGs received sandbox CSP while copied SVGs did not
  • generated page contracts were validated more strictly than hardcoded root contracts

That is now a named bug class in the platform.

7. Prompt Ownership And Review Ownership Are Different Jobs

GoingNinja now treats these as separate responsibilities:

  • Codex scopes the change and writes the audit prompt
  • Claude and Gemini receive a review lane and stay inside that lane
  • the human remains the merge owner

This avoids agent theater and keeps review deterministic.

8. Repeated Audit Findings Are Not Closed Until They Are Written Back

An audit finding is not really closed if it lives only in chat or in one markdown artifact.

Closure requires writeback into at least one durable place:

  • AGENTS.md
  • INVARIANTS.md
  • docs/LEAN_IMPLEMENTATION_CONTRACT.md
  • a reusable template
  • or a deterministic check

9. Local Success Is Not Enough

Another recurring failure mode was assuming local output meant the deployed surface matched it.

The correct sequence is:

  1. fix source
  2. rebuild
  3. verify generated output
  4. verify deployed output
  5. only then close the issue

10. Batch Fixes Beat Tiny Audit Loops

The long audit sequence happened because the early code did not yet have strong contract boundaries.

The operational lesson is:

  • do not rerun external audits after every cosmetic tweak
  • collect the current contract failures
  • patch them as one coherent batch
  • rerun only after the batch is internally green

That is both leaner and more honest.

11. Do Not Declare Lean Too Early

One process failure in this round was declaring the code lean before the current source state had actually passed external review.

That is now an explicit anti-pattern:

  • local confidence is not enough
  • visual neatness is not enough
  • previous audit history is not enough

Only the current audited source state counts.

12. One Snapshot, One Audit Pair

The stable audit loop is now:

  1. patch one coherent batch
  2. build and verify locally
  3. freeze the code
  4. create one fresh snapshot
  5. run Claude and Gemini on that same snapshot

Do not keep editing while an older audit is still running.

13. What Future Repos Should Reuse

Project repos should inherit these lessons immediately:

  • one source of truth per contract
  • generated output is never source
  • no duplicated CSS, SVG, CSP, or route literals
  • no /tmp source of truth
  • unknown routes fail closed
  • equivalent path shapes are validated equally
  • security trust stays tied to the exact runtime primitive
  • repeated audit findings must become rules or checks

14. Invariants Must Fail Before Writes

If a route shape, manifest shape, or output contract is invalid, the build must stop before it writes any staged files.

Do not hide invariant checks inside late render helpers after the filesystem work has already started.

15. Timing Dependencies Must Be Encoded

If code depends on defer, DOMContentLoaded, or worker isolate reuse, that dependency must be encoded in the implementation or removed.

Do not rely on “this file is always loaded that way” as an invisible contract.

16. Shared Assets Must Be Registered Once

If two surfaces use the same stylesheet or SVG, register it once in the shared asset contract.

Two identical registrations with separate cache rules are already one drift away from a bug.

17. Manifests Need Lightweight Validation

If a JSON file drives routing or public output, validate:

  • required fields
  • types
  • duplicates
  • extension or path shape

That check should run at build start, not after a broken page has already been emitted.

18. Feature Detection Must Traverse The Real Tree

When build behavior depends on a token or node type, scan the full tree.

Do not assume the relevant token will always sit at the top level.

Nested lists, quotes, and wrapper nodes are part of the real input shape.

19. Renderer And Runtime Must Share The Same DOM Contract

If the renderer emits selectors that a runtime script consumes later, those selectors must live in one exported contract.

Do not let:

  • the renderer invent class names
  • the runtime rediscover them separately

That is the same drift class as duplicated CSS or duplicated routes.

20. Names Must Match Real Semantics

If two cache policies, route helpers, or status constants have the same value and the same real behavior, they should not keep separate historical names.

Misleading names create fake complexity and invite incorrect future edits.

21. CSS Selectors Are Contracts Too

If HTML emits a class that CSS depends on later, that class belongs in a shared contract just as much as a route or a CSP literal.

Do not leave renderer class names as free strings in one file and stylesheet selectors as free strings in another.

22. Runtime Caching Should Match Runtime Cost

Do not add runtime caches just because a worker isolate can keep them alive.

Cache derived state only when it materially reduces cost and does not add more contract surface than it removes.

For tiny pure renders, recomputation is often leaner than cache invalidation logic.

23. Template Injection Must Fail Loud

If build code injects config into a runtime source file through placeholders, assert that every placeholder exists exactly once.

Silent replacement misses are just broken runtime code with worse debugging.

24. CSP Must Match Real Browser Behavior

A CSP is not correct because it looks strict on paper.

It must also match what the real browser runtime actually does:

  • external script origins
  • inline style emission
  • dynamically injected runtime behavior

25. Mermaid Source Stays Text-Only

Public Mermaid diagrams must stay plain text.

Do not rely on embedded HTML such as <br/> to shape labels.

If a diagram needs line breaks, use Mermaid-native multiline text instead of raw HTML.

26. Generated Route Collisions Must Fail Loud

If two pages or aliases produce the same emitted pathname or header target, the build must stop immediately.

Do not silently skip the second writer.

27. Unbounded Audit Loops Are A Prompt Failure

If a small surface needs dozens of external audit runs, the default assumption should no longer be "the code is still deeply flawed."

The more likely problem is:

  • undefined scope
  • no hard audit cap
  • closure mode activated too late
  • stale snapshots overlapping newer fixes

28. Scope Terms Must Be Defined Before They Are Used

Words such as small scope or small surface are too soft to govern an audit process.

GoingNinja now requires one declared scope class before the first external run:

  • single-surface: one runtime surface or one static builder, with no database schema change, no new auth/provider/data-plane contract, and no cross-repo coordination.
  • multi-surface: two or three tightly coupled surfaces in one repo; shared route, asset, or security contracts are allowed, but there is still no cross-repo rollout contract.
  • system: anything larger than multi-surface, or any cross-repo/provider/data-plane change.

29. Audit Caps Need To Follow The Scope Class

The numeric caps live in one owner page now:

The important stable rule stays the same:

  • the cap follows the declared scope class
  • the cap is carried mechanically in AUDIT_STATE.json
  • if the cap is exceeded, assume a prompt or process bug before assuming the code still needs endless ordinary reruns

30. Contract Fixes Beat Local Workarounds

If a failure comes from a shared contract, the fix must land in that shared contract.

Examples:

  • a viewport problem caused by shared layout rules belongs in shared styles
  • a numbering problem caused by heading handling belongs in the builder
  • a repeated route issue belongs in the route contract or invariant checks

Only genuinely local content errors should be fixed locally in one page.

Do not close a repeated failure class by:

  • adding one page-specific CSS exception
  • patching generated output
  • adding a one-off renderer branch for one page
  • manually correcting the same symptom in multiple files

That kind of patch may look fast, but it weakens the next audit because the underlying drift surface remains open.

31. Vertical Rhythm Needs One Shared Owner

Surface rhythm is not just typography. It also includes:

  • the gap below a divider
  • the gap above the next block
  • sticky offsets between stacked navigation layers
  • the handoff from content to footer meta

If those distances live in different files without one owner, the UI will look almost right and still feel wrong.

GoingNinja now treats page-header spacing, footer divider spacing, sticky offsets, and annotation follow-spacing as one shared surface contract.

32. Figure Captions And Source Notes Are Different Jobs

A figure caption should answer one question:

  • what is shown here

A source note answers a different question:

  • where does this come from

Do not let those jobs collapse into one long paragraph.

GoingNinja now requires:

  • short normalized figure captions
  • short normalized source notes
  • separate renderer classes and styling roles for both

If provenance text becomes long, the fix belongs in the builder normalization contract, not in page-local Markdown edits.

33. Claude Closure Falls Back To Narrow Confirm

Once Claude has already produced one complete closure list on a fresh snapshot, do not keep rerunning the same broad closure prompt after those items are fixed.

The default next step is:

  • freeze the updated snapshot again
  • keep Gemini on that same frozen snapshot
  • ask Claude only to confirm the previously listed blockers on the new snapshot
  • lower Claude effort for that narrow confirm lane if the broad --print path stays silent too long

This keeps the lane in closure mode instead of reopening exploration.

34. Product Proof Must Teach The System

A proof page is not only an internal status log.

It must help a first-time reader understand:

  • what is being proven
  • which example product is used
  • which steps the system follows
  • which evidence already exists
  • which learnings were written back globally

If a proof page reads like repo folklore, it is not doing its job.

35. Product Requirements Must Be Confirmed Before Architecture

GoingNinja now treats Requirements as a separate global stage between Product Brief and Architecture Requirements.

That separation prevents two recurring failures:

  • hiding launch requirements inside product prose
  • inventing architecture before the real launch need is explicit

36. Proof Cases Must Fix Global Contracts First

If a live product-proof case exposes a missing step, unclear gate, or broken template rule, the product repo should not absorb that defect locally.

The correct sequence is:

  1. fix the global manual
  2. fix the global OS template
  3. rerun the product on the corrected contract

That is what turns one project into platform proof.

37. Diagram Readability Beats Diagram Density

If a process diagram becomes readable only after the browser shrinks the full SVG, the diagram is already wrong.

GoingNinja now treats diagram readability as a shared contract:

  • sequential flows default to top-down layout
  • labels stay short and wrap intentionally
  • the SVG keeps its natural width and scrolls when needed
  • the reader should never need to decipher tiny scaled text

38. Provider Baseline Must Be Explicit Before Bootstrap

Product planning cannot start from repo shape alone.

Before bootstrap or deployment can be treated as real work, the system needs an explicit provider baseline:

  • GitHub owner
  • deployment owner
  • DNS owner
  • preview-vs-live decision
  • CLI session or automation token availability
  • billing ownership

If those are missing, the right fix is not to guess through them in the product repo. The right fix is to document the prerequisite globally first.

39. Long Proof Pages Need Guided Navigation

Proof pages are usually longer than normal docs pages because they combine:

  • goal
  • example product
  • setup baseline
  • status
  • evidence
  • learnings

That means proof pages need guided local navigation.

If a proof page is long enough to teach a process, the reader should be able to move through its headings directly from the sidebar instead of scanning one long page blind.

40. New Process Rules Must Be Checked Before They Are Canonized

Not every plausible process idea deserves to become a platform rule.

Before a new rule is written into the wiki, template, or bootstrap path, compare it against:

  • current official vendor documentation
  • stable delivery or readiness best practice
  • the existing platform contract

Do not promote a fresh idea straight from chat into the global system without that check.

41. Compact Navigation Must Behave Like A Real Menu

If the manual switches to a compact navigation shell on smaller viewports, the navigation must act like a real menu:

  • closed by default on compact widths
  • open by default on larger widths
  • able to open through a native interaction primitive, not only through fragile runtime state
  • visually attached to the sticky header without a drifting gap
  • the same width as the shared shell at that breakpoint
  • closed again after the reader chooses a destination

If any of those behaviors are missing, the bug belongs in the shared manual navigation contract, not in one proof page.

42. UI Audits Must Test Stateful Navigation, Not Only Static Layout

It is not enough for a UI audit to read one static screenshot and approve the typography.

For navigation-heavy docs surfaces, the audit lane must also check:

  • desktop to compact breakpoint transitions
  • sticky header and sticky menu handoff
  • menu open and close state
  • what happens after a navigation click on compact viewports
  • what happens when a compact viewport is resized back to desktop width
  • the actual delivered host, not only a raw build or a static screenshot

Otherwise the audit can praise a surface that still fails in real use.

43. Sticky Offsets Must Be Measured Or Strictly Owned

The manual menu loop returned because the sticky handoff was treated as a cosmetic spacing tweak instead of a layout contract.

The stable rule is:

  • if a sticky surface must meet another sticky surface exactly, its offset must come from the real shared owner
  • guessed breakpoint offsets are only acceptable as fallback values
  • compact navigation state must not share the same interaction primitive as desktop navigation if that coupling can hide the desktop menu after a resize

44. Shared Runtime Assets Must Bust Stale Browser State

If shared CSS or JS assets keep stable filenames across deploys, a browser can render a mixed state:

  • new HTML
  • old CSS
  • or old runtime JS

That class of drift is especially dangerous for interactive shell contracts such as compact navigation because the markup can look current while the behavior still follows an older runtime.

The stable rule is:

  • shared static assets must expose a versioned href or fingerprinted path
  • deploy verification must not assume that Cache-Control: no-cache alone is enough to prevent mixed asset state

Otherwise the audit can praise a surface that still fails in real use.

45. Security Headers Must Match Shared Runtime Ownership

If every manual page loads one shared runtime such as manual-nav.js, the page CSP must allow that runtime on every page in the surface.

It is not enough for one proof page to work because it happens to need a looser CSP for another reason.

The stable rule is:

  • page-level CSP must be derived from the full shared runtime contract, not from one optional feature such as Mermaid alone
  • audits must compare the root page and at least one representative internal page
  • a UI bug that appears only on some pages can still be a global delivery bug

46. Public Manual Lists Should Stay Flat

The public manual is easier to scan when list structures stay flat and when continuation lines follow the text instead of drifting under a nested marker stack.

The stable rule is:

  • public manual pages should prefer flat bullets or short tables over nested list levels
  • TOC numbering and list markers need one shared spacing contract
  • mixed inline list items such as link + trailing sentence need one shared rendered body wrapper; CSS must not rely on anonymous text nodes
  • nested markdown lists in public manual pages now fail the build instead of silently drifting the style surface