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
54 changes: 36 additions & 18 deletions .agents/skills/docs-driven-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ user, maintaining an existing documented feature, or improving the harness.
An internal refactor need not invent a new tutorial. Existing behavioral and
unit tests still matter, particularly for cases a user guide should not enumerate.

Follow [AGENTS.md](../../../AGENTS.md). Read the relevant feature's template and
scenario before changing its behavior. Consult the
Follow [AGENTS.md](../../../AGENTS.md). Read the relevant feature's scenario and
its registered narrative source before changing its behavior. Consult the
[pipeline contract](../../../docs/architecture/documentation-pipeline.md) for
current APIs, capture defaults, encoding limits, and examples. Do not duplicate
that technical manual in this skill.
capture defaults, encoding limits, and examples, and the
[executable document boundary](../../../docs/architecture/executable-documents.md)
for the maintained SDK and N3 adapter. This skill governs N3's workflow; the
portable SDK does not require it. Do not duplicate the API manuals here.

## The development and feedback loop

1. **Describe the experience.** Start from what the user wants to do, what they
act on, what feedback they see, and how they finish or recover. Draft or adjust
the owning user-guide template before or alongside implementation. Write in
the owning user-guide narrative before or alongside implementation. Write in
the user's vocabulary; implementation notes belong in architecture docs.
2. **Make the important promises executable.** Extend the matching scenario with
meaningful outcomes. For a regression, reproduce the failure before fixing it
Expand Down Expand Up @@ -62,33 +64,47 @@ its user explanation and executable evidence land with its implementation.

## Sources of truth

Each current guide feature has one template, one scenario, and one registry entry:
Each guide feature has one scenario, one registry entry, and exactly one narrative
source. `hand-tool` and `navigation` author their narrative in Rust through the
N3 `Guide` adapter and register `template: None`. Other features retain their
registered templates. Do not keep both prose forms for one feature.

| Source | Owns |
| -------------------------------------------------------------------- | -------------------------------------------------- |
| [docs/templates](../../../docs/templates/) | User narrative and semantic bindings |
| [src/documentation/scenarios](../../../src/documentation/scenarios/) | Real replay and behavioral assertions |
| [features.rs](../../../src/documentation/features.rs) | Feature registration |
| [input/bindings.rs](../../../src/input/bindings.rs) | Production key bindings, labels, and replay inputs |
| [ui/controls.rs](../../../src/ui/controls.rs) | Control identities and witnessed UI names/paths |
| [docs/guide](../../../docs/guide/) | Generated user pages, media, and evidence manifest |
| Source | Owns |
| -------------------------------------------------------------------- | ----------------------------------------------------- |
| [docs/templates](../../../docs/templates/) | Retained legacy narratives and semantic bindings |
| [src/documentation/scenarios](../../../src/documentation/scenarios/) | Real replay, assertions, and Rust-authored narratives |
| [features.rs](../../../src/documentation/features.rs) | Feature registration and narrative-source selection |
| [input/bindings.rs](../../../src/input/bindings.rs) | Production key bindings, labels, and replay inputs |
| [ui/controls.rs](../../../src/ui/controls.rs) | Control identities and witnessed UI names/paths |
| [docs/guide](../../../docs/guide/) | Generated user pages, media, and evidence manifest |

Edit the sources, never the generated guide or its media by hand. The browser
preview displays these same files; it does not own another content tree or
approve a baseline.
For paired Reader and Contributor review, `just docs build --out .cache/docs-candidate`
captures one replay into a fresh candidate tree without accepting the baseline.

`just fmt-docs` formats authored Markdown and `.md.in` templates through the
version-pinned `tools/format_docs.py` wrapper on the native host. It needs
Node.js/npm with `npx` there. The wrapper checks that all template bindings keep
their order before writing any template.
Generated guides are excluded; after a template formatting change, regenerate
with `just docs update` and review the resulting text through the same pipeline.
Rust-authored narratives follow Rust formatting. Generated guides are excluded;
when formatting changes narrative output, regenerate with `just docs update` and
review the resulting text through the same pipeline.

Keep the audience boundary explicit. Repository-owned, GitHub-hosted documents
such as `TODO.md`, contributor instructions, and engineering/research notes may
link to user docs. The user guide and its navigation must never link back to
those documents. A shared directory does not imply a shared audience; keep
planning and contributor references out of templates and generated guide indexes.
planning and contributor references out of reader narratives and generated guide indexes.

Rust-authored guides use typed control, shortcut, and media handles from `Guide`.
Labels come from witnessed controls and canonical bindings; captures still run
through `Session`. A label or resource handle does not replace a meaningful
behavioral assertion. Keep the prose beside the replay and use the adapter's
finish step so registered and captured evidence stay accountable.

For retained templates:

- Use `{{shortcut:selection.duplicate}}` for an application shortcut. The binding
registry supplies the `<kbd>` keys. Replay it with `Session::shortcut`, or
Expand All @@ -109,7 +125,7 @@ A documented contract must not silently drift. Preserve failures for violated
assertions, missing or unwitnessed controls, unknown bindings, incorrect media
kinds, missing or unreferenced captures, changed output, and orphaned artifacts.
Retiring a feature means explicitly reconciling its implementation, registry,
scenario, template, references, and generated artifacts.
scenario, narrative source, references, and generated artifacts.

Treat a regression that escapes an intended assertion as a coverage problem to
repair. A page's existence does not prove every sentence or every possible
Expand Down Expand Up @@ -137,6 +153,8 @@ it does not establish cross-renderer pixel equivalence. Use `just test`
for the full native suite and `just test-metal` for focused capture checks.
For skill or hand-authored contributor-doc changes alone, validate instructions
and links; unchanged app/media output does not require regeneration.
For portable framework changes, `just doc-framework-test` provides focused SDK
and consumer checks; N3 adapter changes still require native replay and `just verify`.

## Evolve the harness when the user story needs it

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
.cache/ci/linux-amd64/target/debug/.fingerprint
.cache/ci/linux-amd64/target/.rustc_info.json
.cache/ci/linux-amd64/home/.npm
key: n3-v1-ubuntu24-linux-amd64-${{ steps.environment.outputs.image }}-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'vendor/**') }}
key: n3-v1-ubuntu24-linux-amd64-${{ steps.environment.outputs.image }}-${{ hashFiles('Cargo.toml', 'crates/**/Cargo.toml', 'Cargo.lock', 'vendor/**') }}
- name: Check formatting, lint, tooling, and focused regressions
env:
N3_CI_FAILURE_ARTIFACTS: "1"
Expand Down Expand Up @@ -95,7 +95,7 @@ jobs:
.cache/ci/linux-amd64/target/debug/.fingerprint
.cache/ci/linux-amd64/target/.rustc_info.json
.cache/ci/linux-amd64/home/.npm
key: n3-v1-ubuntu24-linux-amd64-${{ steps.environment.outputs.image }}-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'vendor/**') }}
key: n3-v1-ubuntu24-linux-amd64-${{ steps.environment.outputs.image }}-${{ hashFiles('Cargo.toml', 'crates/**/Cargo.toml', 'Cargo.lock', 'vendor/**') }}
- name: Replay every guide feature and check exact artifacts
env:
N3_CI_FAILURE_ARTIFACTS: "1"
Expand Down Expand Up @@ -143,7 +143,7 @@ jobs:
target/debug/build
target/debug/.fingerprint
target/.rustc_info.json
key: n3-v1-macos15-${{ runner.os }}-${{ runner.arch }}-${{ steps.environment.outputs.platform }}-${{ hashFiles('rust-toolchain.toml', 'Cargo.toml', 'Cargo.lock', 'vendor/**') }}
key: n3-v1-macos15-${{ runner.os }}-${{ runner.arch }}-${{ steps.environment.outputs.platform }}-${{ hashFiles('rust-toolchain.toml', 'Cargo.toml', 'crates/**/Cargo.toml', 'Cargo.lock', 'vendor/**') }}
- name: Restore the pinned just installation
id: just
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
Expand Down Expand Up @@ -221,7 +221,7 @@ jobs:
target/wasm32-unknown-unknown/release/build
target/wasm32-unknown-unknown/release/.fingerprint
target/.rustc_info.json
key: n3-v2-wasm-release-${{ runner.os }}-${{ runner.arch }}-${{ steps.environment.outputs.platform }}-${{ hashFiles('rust-toolchain.toml', 'Cargo.toml', 'Cargo.lock', 'vendor/**') }}
key: n3-v2-wasm-release-${{ runner.os }}-${{ runner.arch }}-${{ steps.environment.outputs.platform }}-${{ hashFiles('rust-toolchain.toml', 'Cargo.toml', 'crates/**/Cargo.toml', 'Cargo.lock', 'vendor/**') }}
- name: Restore pinned browser build tools
id: tools
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
Expand Down
2 changes: 2 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"/TODO.md",
"/Cargo.lock",
"/docs/guide/**",
"/crates/doc-example-config/baseline/**",
"/crates/doc-harness/docs/guide/**",
"/docs/preview/vendor/**",
"/vendor/**",
"/examples/**",
Expand Down
66 changes: 42 additions & 24 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,29 +69,35 @@ boundaries. The current Editor still depends on egui and is not a public kernel

## Code organization

Keep one application crate until a real consumer and a clear dependency boundary
justify extraction. Prefer focused modules over speculative crates, public APIs,
or generic frameworks.
Keep N3 as one application crate. The workspace also maintains the portable
`executable-docs` SDK in `crates/doc-harness` and its consumer examples in
`crates/doc-example-config`; N3's documentation adapter is a real SDK consumer.
This extraction is justified by a tested boundary between application replay and
document composition/publication. It does not make the editor a public kernel.
Prefer focused modules over further speculative crates or APIs. See
[executable documents](docs/architecture/executable-documents.md) for this boundary.

Read [platform boundaries and performance](docs/architecture/platform-boundaries.md)
before changing host adapters or platform-dependent behavior. Share product
semantics, keep target selection at module boundaries, and preserve each host's
execution policy. Browser constraints must not lower the primary native target's
capabilities, performance policy, or verification baseline.

| Location | Responsibility |
| -------------------- | --------------------------------------------------------------------- |
| `src/model/` | Authored documents, units, native text codec, geometry evaluation |
| `src/asset_io/` | Format adapters, resource resolution, native document persistence |
| `src/scene/` | Internal imported scene model, validation and pose evaluation |
| `src/scene_view.rs` | Transient asset inspection and playback; separate from edit history |
| `src/editor/` | Selection, edits, sessions, history, transform policies |
| `src/input/` | Key mapping, semantic actions, pointer and navigation routing |
| `src/render/` | Camera, wgpu rendering, derived visual feedback |
| `src/ui/` | Panels, controls, gizmo, rulers |
| `src/native.rs` | Window lifecycle, native events, dialogs, filesystem effects |
| `src/settings/` | Typed global preferences, validation, merge policy, storage interface |
| `src/documentation/` | Headless replay, virtual input, annotations, capture, scenarios |
| Location | Responsibility |
| ---------------------------- | ----------------------------------------------------------------------------- |
| `src/model/` | Authored documents, units, native text codec, geometry evaluation |
| `src/asset_io/` | Format adapters, resource resolution, native document persistence |
| `src/scene/` | Internal imported scene model, validation and pose evaluation |
| `src/scene_view.rs` | Transient asset inspection and playback; separate from edit history |
| `src/editor/` | Selection, edits, sessions, history, transform policies |
| `src/input/` | Key mapping, semantic actions, pointer and navigation routing |
| `src/render/` | Camera, wgpu rendering, derived visual feedback |
| `src/ui/` | Panels, controls, gizmo, rulers |
| `src/native.rs` | Window lifecycle, native events, dialogs, filesystem effects |
| `src/settings/` | Typed global preferences, validation, merge policy, storage interface |
| `src/documentation/` | Headless replay, virtual input, annotations, capture, scenarios |
| `crates/doc-harness/` | Portable document composition, evidence, audience exports, artifact lifecycle |
| `crates/doc-example-config/` | Standalone CLI and library consumers of the documentation SDK |

Keep code, identifiers, comments, tests, logs, and authored UI strings in English.
Explain non-obvious behavior and platform limitations near the owning code.
Expand All @@ -118,19 +124,26 @@ Native and web share one feature UI and user guide. Follow the
[shared product contract](docs/architecture/platform-boundaries.md#one-product-experience)
for capability-based availability and the boundary with contributor documentation.

Every guide feature owns one Rust scenario in `src/documentation/scenarios/` and
one template in `docs/templates/`, registered in
`src/documentation/features.rs`. Edit those sources; never hand-edit generated
pages, media, or the manifest in `docs/guide/`.
Every guide feature owns one Rust scenario in `src/documentation/scenarios/`
and exactly one narrative source, selected in `src/documentation/features.rs`.
Rust-authored guides compose their narrative in the scenario through the N3
`Guide` adapter and register `template: None`; retained legacy features use one
`docs/templates/*.md.in` template. `hand-tool` and `navigation` are Rust-authored.
Do not keep a parallel template or generated-prose copy for an authored guide.
Edit the registered source; never hand-edit pages, media, or the manifest in
`docs/guide/`.

- Assert actual behavior, including meaningful intermediate states for a gesture.
Fixture setup may prepare state; an illustrated interaction must use production
input routing and the real UI/renderer.
- Bind labels and paths to witnessed controls. Bind callouts to live control IDs,
not stale screen coordinates. Virtual input and annotations only paint; they
must not alter focus, hover, selection, or document state.
- Use `{{shortcut:semantic-id}}` for application shortcuts, `{{control:id}}` for
witnessed menu paths, and `{{key:Name}}` / `{{modifier:name}}` for literal
- Rust-authored guides use the `Guide` adapter's typed control, shortcut, and
captured-resource handles. A presented label is not evidence that an action
ran; retain the actual replay and behavioral assertions.
- In retained templates, use `{{shortcut:semantic-id}}` for application shortcuts,
`{{control:id}}` for witnessed menu paths, and `{{key:Name}}` / `{{modifier:name}}` for literal
text-entry keys or physical gesture modifiers. Do not copy remappable keys
into prose or scenario values. Replay actions with `Session::shortcut` and its
held-key helpers; reserve raw keys for literal input or intentional ownership
Expand All @@ -146,14 +159,18 @@ pages, media, or the manifest in `docs/guide/`.

The [pipeline contract](docs/architecture/documentation-pipeline.md) documents
replay, timing, bindings, overlays, encoding limits, and authoring examples.
`just docs build --out .cache/docs-candidate` runs one replay and writes fresh
Reader and Contributor review trees. It does not accept a canonical baseline;
`just docs check/update` retain their existing reader-guide roles.

## Iteration and verification

For an implementation change:

1. Identify the owning model/input/UI boundary and any affected guide scenario.
2. Make a focused change and add meaningful behavioral regressions where needed.
For visible interactions, update the owning scenario and template together.
For visible interactions, update the owning scenario and its registered
narrative together.
3. If guide output intentionally changes, run `just docs update`, then inspect the
generated text, stills, and animation playback before accepting the baseline.
Use the native host renderer; local development must not require CI infrastructure.
Expand All @@ -167,7 +184,8 @@ Contributor setup is `just setup` (Node.js 24/npm with `npx`, a warmed cache for
the Oxfmt version pinned in `tools/format_docs.py`, and a repository-local
pre-push hook). `just fmt` formats Rust and authored docs;
`TODO.md` is excluded. Generated guide files are excluded from formatting: format
their templates, then regenerate through the ordinary pipeline when needed.
the authored Rust scenario or retained template, then regenerate through the
ordinary pipeline when its output intentionally changes.
The pre-push hook verifies a clean current `HEAD`, not arbitrary refs or dirty
working content. `just test`, `just docs update/check`, and `just verify` run
natively, as does the pre-push hook. Developer experience comes first: never make
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ repository's pre-push hook. The optional CI container supplies Node. Run
Keep changes focused and describe the behavior they add or fix. For implementation
changes, run `just verify` and report any device interactions that still
need manual validation. User-visible changes should update their owning guide
scenario and template, with generated media reviewed alongside the code.
scenario and registered narrative, with generated media reviewed alongside the code.

The pre-push hook requires a clean checkout and pushed commits matching `HEAD`,
then runs `just verify`. It never stages, formats, commits, or pushes for you.
Expand Down
Loading
Loading