Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/ADD_A_MODULE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ npm run modules:compat -- <id> # Octatrack: installs beside every

## What CI runs

- **Documentation-only pull requests:** licence, generated catalogue, release-note coverage, module contract, tutorial and screenshot-provenance validation. No application test suite, bundle, Windows runner or native compiler.
- **Documentation-only pull requests:** licence, generated catalogue, release-note coverage, module contract, tutorial and screenshot-provenance validation, plus the catalogue tests (`src/catalog`, about 15 seconds), because some of them check that the guides link to files that exist. No full application test suite, bundle, Windows runner or native compiler.
- **Application or behaviour changes:** the full `npm run check` (lint, tests, types, build).
- **Only a pull request that changes module source, the module build or the committed packages:** the Docker compile that must reproduce the committed packages. Changes to module folders or their path handling also run the Windows check. These are the same inputs the release uses to decide whether to rebuild the modules.
- **After the merge:** the release verifies the merge approval, re-verifies the generated files, licences and module records, then type-checks and bundles what the pull request already tested. It rebuilds the modules only if module inputs changed.
Expand Down
2 changes: 1 addition & 1 deletion docs/APP_DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ Record real device outcomes against the exact source, base, package hashes and v

## Documentation validation and deployment scope

Run `npm run check -- --base origin/main` before committing. The shared `scripts/change-scope.mjs` compares actual changes, including manifest prose and generated catalogues. Documentation-only edits validate licences, catalogue freshness, module contracts, tutorials and capture provenance without the application suite, lint, typecheck, bundle or native compilation. Unknown paths and source/behaviour changes retain the full app checks.
Run `npm run check -- --base origin/main` before committing. The shared `scripts/change-scope.mjs` compares actual changes, including manifest prose and generated catalogues. Documentation-only edits validate licences, catalogue freshness, module contracts, tutorials and capture provenance, then run the catalogue tests (some check that the guides link to files that exist), without the full application suite, lint, typecheck, bundle or native compilation. Unknown paths and source/behaviour changes retain the full app checks.

PR and Pages firmware builds follow firmware source and build identities rather than broad SDK directory changes. Digi documentation/version labels do not rebuild Octatrack packages. Source pins, build recipes, toolchains, code, linking metadata and package changes retain their native gates. Pages still bundles the site to publish updated documentation. Generated catalogue edits only redeploy the Worker when its consumed module fields change; a manual Worker dispatch still deploys.

Expand Down
4 changes: 2 additions & 2 deletions docs/module-guides/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ The gate does not prove runtime behaviour, DSP placement, cycles or hardware com

Shared behaviour on the Octatrack follows Elekloader's hook bus ([ADAPTING.md](https://github.com/irpina/elekloader/blob/main/docs/ADAPTING.md), "Do not patch the shared sites: subscribe"). The base owns each event's stock site and calls every subscribed handler in a fixed order. A module adds a handler with `subscribe` entries of `event`, `fn` and `order`, for example `{"event": "ev_play_increment", "fn": "mymod_rate", "order": 50}`. Lower `order` runs first. Each event's registry entry gives its C prototype and says what a return value means, for example whether a handler can take the event so that later handlers do not see it.

The registry is `sdk/machines/octatrack/events.json`. Its first two events, `ev_play_increment` and `ev_voice_bind`, and subscribe support in the USB loader are still being built. Until they land, the gate checks the two planned sites from a small fixture in `scripts/module-compat.py`, and no module can subscribe yet. Do not add a new raw patch at either site in the meantime.
The registry will be a file called `events.json` beside `sdk/machines/octatrack/compatibility.json`. Its first two events, `ev_play_increment` and `ev_voice_bind`, and subscribe support in the USB loader are still being built. Until they land, the gate checks the two planned sites from a small fixture in `scripts/module-compat.py`, and no module can subscribe yet. Do not add a new raw patch at either site in the meantime.

### Propose an event

Propose an event when the gate says two behaviour hooks meet, or when you need a site that another module or the base already patches:

1. Open a pull request that adds one entry to `sdk/machines/octatrack/events.json`: the name (`ev_` and what happens), the stock site (address and length, whole instructions), when it runs (task or interrupt level), the handler's C prototype and its order rule. Addresses and lengths only: no stock bytes.
1. Open a pull request that adds one entry to the registry (`events.json`, once it exists): the name (`ev_` and what happens), the stock site (address and length, whole instructions), when it runs (task or interrupt level), the handler's C prototype and its order rule. Addresses and lengths only: no stock bytes.
2. Say which modules patch that site today. Until they subscribe, list each such pair in `compatibility.json` as `pending-migration`, with the event and `until`.
3. The owner reviews the entry. Every later module subscribes to it instead of patching.

Expand Down
5 changes: 3 additions & 2 deletions scripts/check.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ if (passed) {
console.log(`Module changelogs: ${notes.modules} modules, ${notes.releases} releases`)
} catch (error) { console.error(error.message); passed = false }
}
// Documentation uses the same import policy as publication without running firmware gates.
if (passed && documentationOnly) passed = await run('sdk:imports:check')
// Documentation uses the same import policy as publication without running firmware gates. The catalogue tests read Markdown
// (the module guides' links, the agent files, the pull request template), so a prose-only change can break them and must run them.
if (passed && documentationOnly) passed = await run('sdk:imports:check') && await run('test', ['src/catalog'])
if (passed && !documentationOnly) {
const results = buildOnly
? [await build()]
Expand Down
11 changes: 9 additions & 2 deletions src/tooling/check.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ function documentationCheck(missingNotes = false, failure = '') {
} finally { rmSync(folder, { recursive: true, force: true }) }
}

it('checks documentation without starting the application suite, build or generators', () => {
it('checks documentation without starting the full application suite, build or generators', () => {
const result = documentationCheck()
expect(result.status, result.stderr).toBe(0)
expect(result.stdout).toContain('Documentation check passed')
expect(result.stdout).toContain('Module changelogs: 1 modules, 1 releases')
expect(result.scripts).toEqual(['licenses:check', 'machines:check', 'modules:check', 'sdk:imports:check'])
expect(result.scripts).toEqual(['licenses:check', 'machines:check', 'modules:check', 'sdk:imports:check', 'test'])
})

it('catches imported-source drift before a documentation PR can reach publication', () => {
Expand All @@ -120,6 +120,13 @@ it('catches imported-source drift before a documentation PR can reach publicatio
expect(result.scripts).toEqual(['licenses:check', 'machines:check', 'modules:check', 'sdk:imports:check'])
})

it('runs the catalogue tests that read Markdown, so a prose-only change cannot break main unseen', () => {
const result = documentationCheck(false, 'test')
expect(result.status).toBe(1)
expect(result.stdout).toContain('Documentation check FAILED')
expect(result.scripts).toEqual(['licenses:check', 'machines:check', 'modules:check', 'sdk:imports:check', 'test'])
})

it('requires current-version release notes even on the documentation-only validation path', () => {
const result = documentationCheck(true)
expect(result.status).toBe(1)
Expand Down
Loading