For contributors and maintainers
Change the source, then prove the shipped tree.
IdeaForge has no dependencies and no build step. Its architecture keeps interview logic separate from browser APIs, while the test and delivery pipelines exercise the same static files that users receive.
Architecture and boundaries
Source is split by responsibility so most behaviour can run under Node without a DOM, network, real clock, or mocking framework. Dependencies flow from the UI into runtime and core, while browser-facing services sit beside that path.
| Directory | Owns | Boundary |
|---|---|---|
src/core/ |
Sessions, coverage, prompts, synthesis, exports, backup format validation, and other pure decisions. | No DOM, network, clock, or randomness. |
src/runtime/ |
Turn, synthesis, gain, and hands-free orchestration. | Providers, time, and effects are injected. |
src/providers/ |
Inference requests, authentication, model discovery, and provider errors. | The only source directory that directly owns model network access. |
src/store/ |
IndexedDB sessions and preferences, backup persistence/import integration, and the encrypted keyring. | Browser storage stays behind small adapters. |
src/voice/ |
Recording, silence detection, speech recognition, transcription, and speech. | Browser capability is proved by behaviour, not presence alone. |
src/ui/ |
The application shell, panels, navigation, and browser coordination. | The only layer that directly owns the DOM. |
There is no package installation or compilation phase. Browser modules are served as
written. tools/assemble-site.mjs only copies the publishable tree for
browser checks, Pages, and packaging; it does not bundle or rewrite it.
The purity gate
tools/lint-purity.mjs scans src/core/ and
src/runtime/ for platform globals such as window,
document, browser storage, navigator, and
fetch. It runs first in npm test.
Use the smallest test that can disprove the change
npm test
npm run test:graph
npm run test:browser:required
npm run test:all
| Check | What it proves | When to run it |
|---|---|---|
npm test |
The purity boundary and the Node unit suite. | Continuously while changing pure or injected behaviour. |
npm run test:graph |
Syntax, imports, and the shipped module graph. | After moving, adding, or rewiring modules. |
npm run test:browser:required |
IndexedDB, WebCrypto, media, speech, service workers, CSP, the guide, and the assembled site in headless Chrome. | For any browser-owned surface. Missing Chrome is a failure. |
npm run test:all |
The complete local gate: unit, graph, and required browser checks. | Before pushing a branch. |
Tests use Node's built-in runner, injected clocks and fetch functions, and browser
probes under test/browser/. A real local-model run is a separate,
deliberate check through npm run validate:local; it is not a replacement
for the deterministic suite.
Extend through the existing seams
DIMENSIONS. Coverage initialization, selection, prompts,
synthesis, and export derive from it; then inspect the few documented labels and
engine branches that do not.
index.html, keep active-session ownership in
src/ui/app.js, and place panel-specific DOM work in its own UI module.
src/voice/, and prove event ordering and no-tap recovery with the
browser fixtures.
The focused
repository
skills add-provider and change-voice-and-driving carry
the subsystem-specific checks. A new file under src/ must also appear in
sw.js; the wiring tests enforce that cold offline path.
Contribute a focused change
git clone https://github.com/jaypetez/ideaforge.git
cd ideaforge
npm test
npm run serve
Node 22 or newer is enough. There is no npm install. Serve the repository
over HTTP because ES modules, IndexedDB, and the service worker do not work from
file://.
- Read the relevant architecture and invariant sections, then make the smallest coherent change without introducing a dependency or build step.
- Add a test that would have caught the failure. Use a browser probe when Node cannot observe the affected API or user flow.
-
Run focused checks while editing, then
npm run test:allbefore pushing. -
Open a pull request against
main, state what was verified, and add the release-note label that describes the change. Leave merging to the reviewer unless you were explicitly asked to merge.
The complete contributor policy, provider checklist, assistant setup, and release boundary live in CONTRIBUTING.md.
Continuous integration
The CI workflow runs npm test and the module graph on Linux, Windows, and
macOS with Node 22 and 24. A separate Ubuntu job runs the required browser suite.
Branch protection requires one stable aggregator named ci; it fails
unless every matrix and browser job succeeds, including cancelled or skipped jobs.
The workflow is read-only and has no install or package-cache step. Do not bypass the aggregator or add path filters that can leave a required check waiting forever.
GitHub Pages publishes the tested tree
- A successful CI run must come from a push to
main. - The Pages workflow verifies the matching
cijob and confirms that its tested commit is still the exact tip ofmain. tools/assemble-site.mjscopies the application, guide, and generated screenshots intodist/.- The workflow checks the tip again immediately before deploying, so an older run cannot overwrite a newer main branch.
The guide is part of that assembled tree but is deliberately excluded from the app service worker. A failed documentation navigation must never fall back to the application shell.
Releases are tag-driven and separate from Pages
Release work uses the explicitly invoked
release skill. Preparation opens a version PR; it is not permission to merge or
publish.
An authorised maintainer publishes by pushing a vMAJOR.MINOR.PATCH tag at
the approved, green commit on main.
The release workflow first checks that the tag, package.json, and
src/version.js agree, proves the commit belongs to main, and
reruns npm run test:all. Only then may write-enabled jobs publish the
reproducible source archives, SHA256SUMS, and the multi-architecture
container image. Pages deployment remains an independent main-branch pipeline.
Coding-assistant discovery
Open the repository root so each client can discover the shared instructions and
skills. AGENTS.md owns the working loop, CLAUDE.md owns the
implementation invariants, and .claude/skills/ contains the one shared
definition of each project skill.
| Client | Entry point | Documentation review adapter |
|---|---|---|
| Claude Code | CLAUDE.md, which imports AGENTS.md |
ideaforge-docs-review-claude |
| GitHub Copilot CLI and VS Code | .github/copilot-instructions.md plus the shared references |
ideaforge-docs-review-copilot |
Use update-documentation when documentation should be changed and
review-ideaforge-documentation for an exact, read-only drift review.
Their client adapters expose only read tools and stop when the requested diff is not
available.
copilot instruction list --json
copilot skill list --json
In Copilot CLI, /env, /instructions,
/skills, and /agent show the loaded configuration. In
Claude Code, use /memory and /skills. In VS Code, use the
Chat customization and diagnostics views. Start a fresh session after changing
instructions, skills, or agents, and do not bypass workspace trust or normal tool
approval to make discovery work.