From e9d667da49a481ff87faf5a1603dbfac32bd7782 Mon Sep 17 00:00:00 2001 From: JasonStys Date: Tue, 10 Nov 2026 00:17:46 -0800 Subject: [PATCH] docs: publish reviewed engine guide and validation handbook --- .gitattributes | 2 + README.md | 5 ++ docs/file-catalog.md | 9 +++ docs/handbook.md | 53 ++++++++++++++++ .../documentation-refresh-2026-11-09.md | 37 +++++++++++ docs/reports/practical-workflows-20261109.md | 18 +++--- docs/reports/project-guide.docx | Bin 0 -> 45218 bytes docs/reports/publications.json | 59 ++++++++++++++++++ 8 files changed, 174 insertions(+), 9 deletions(-) create mode 100644 docs/handbook.md create mode 100644 docs/reports/documentation-refresh-2026-11-09.md create mode 100644 docs/reports/project-guide.docx create mode 100644 docs/reports/publications.json diff --git a/.gitattributes b/.gitattributes index 9df3350..ce1d76a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,3 +6,5 @@ *.png binary *.ppm binary docs/reports/generated/* linguist-generated=true +*.docx binary +*.xlsx binary diff --git a/README.md b/README.md index e813dd9..542bf2b 100644 --- a/README.md +++ b/README.md @@ -158,3 +158,8 @@ unverified compilers/platforms. See [docs/operations.md](docs/operations.md). ## License [MIT](LICENSE) +## Documentation editions + +Start with the [organized handbook](docs/handbook.md) for current usage, design, security and test guidance. Reviewed downloadable editions: [project-guide.docx](docs/reports/project-guide.docx). + +[Publication identities and source scope](docs/reports/publications.json) · [Documentation validation record](docs/reports/documentation-refresh-2026-11-09.md). Historical results retain their own tested revision and date. diff --git a/docs/file-catalog.md b/docs/file-catalog.md index a82751e..c369a08 100644 --- a/docs/file-catalog.md +++ b/docs/file-catalog.md @@ -95,3 +95,12 @@ For declaration-level locations, see the generated [code index](code-index.md). | `docs/reports/test-summary.md` | Records test scope, dated local results, and limitations. | | `docs/reports/validation.md` | Records compiler, SDL, repository, artifact, and pending hosted-CI validation. | | `docs/reports/generated/.gitkeep` | Preserves the otherwise-empty directory used for generated CI reports. | + +## Reviewed documentation editions + +| File | Responsibility | +| --- | --- | +| `docs/handbook.md` | Organizes current usage, design, security and validation guidance. | +| `docs/reports/project-guide.docx` | Reviewed readable Word guide of the cited public source and dated evidence. | +| `docs/reports/publications.json` | Binds exact Office bytes, source revision, page review and workflow observations. | +| `docs/reports/documentation-refresh-2026-11-09.md` | Records publication checks, current review and historical-evidence limits. | diff --git a/docs/handbook.md b/docs/handbook.md new file mode 100644 index 0000000..46a63de --- /dev/null +++ b/docs/handbook.md @@ -0,0 +1,53 @@ +# Forge2D Engine handbook + +By Jason Stys. + +The implementation adds bidirectional collision category and mask filters, versioned scene migration, deterministic state hashes and initial/final overlap CSV inspection. + +Supports practical game-world collision layers and reproducible debugging against independent geometry oracles. + +## Read the documentation + +| Edition | Audience and contents | +| --- | --- | +| [project-guide.docx](reports/project-guide.docx) | User and developer guide: purpose, current usage, design, boundaries and source references. | + +The editable Markdown remains the maintenance source. The Word files are readable editions, and the workbook is an evidence index rather than a test runner. See [publication identities and review](reports/publications.json) and the [documentation refresh record](reports/documentation-refresh-2026-11-09.md). + +## Current usage and help + +[README quick start](../README.md) is the entry point. Use the project-specific guides below before changing inputs, operating modes or deployment assumptions. + +### Usage and operations + +- [operations](operations.md) + +### Design and contracts + +- [adr/0001 headless core and optional sdl3](adr/0001-headless-core-and-optional-sdl3.md) +- [api](api.md) +- [architecture](architecture.md) +- [complexity](complexity.md) +- [research](research.md) + +### Security and validation + +- [testing](testing.md) + +## Historical results and reproduction + +The reviewed source is [`43fd93f79043231230a4c19346bdb8a4c356d9ce`](https://github.com/JasonStys/forge2d-engine/tree/43fd93f79043231230a4c19346bdb8a4c356d9ce). The observed functional workflow baseline is `43fd93f79043231230a4c19346bdb8a4c356d9ce`; those observations are recorded at `2026-11-10T05:25:40.628667+00:00`. They do not certify an unrun later revision. + +- [Detailed recorded validation](reports/practical-workflows-20261109.md) +- [Current Actions](https://github.com/JasonStys/forge2d-engine/actions) records later integration checks separately. +- Preserve dated measurements and follow the existing testing guide to reproduce them; a test-source inventory alone does not establish execution. + +## Practical boundaries + +- Category/mask filtering selects AABB query candidates; it does not add physical collision response, enter/exit callbacks or navigation changes. +- Filter words change numeric state fingerprints even for legacy default filters; replay input grammar remains version 1. +- Raw queries cannot establish current entity-generation validity; World owns lifetime checks. This is a fictional integer 2D game engine. + +## Maintaining these editions + +Update the editable usage/design/test documents first. Rebuild and visually review every Word page and workbook tab before replacing an edition; verify the exact binary digests and evidence source in publications.json. Keep account data, logs with secrets, installed-app state and private test stores out of documentation. Source and release assets retain their existing security and licensing boundaries. diff --git a/docs/reports/documentation-refresh-2026-11-09.md b/docs/reports/documentation-refresh-2026-11-09.md new file mode 100644 index 0000000..a366b82 --- /dev/null +++ b/docs/reports/documentation-refresh-2026-11-09.md @@ -0,0 +1,37 @@ +# Documentation refresh — 2026-11-09 + +By Jason Stys. + +This documentation-only edition describes source `43fd93f79043231230a4c19346bdb8a4c356d9ce`. It does not change application behavior, accounts, private data, installers or published releases. + +## Published editions and completed review + +| File | Bytes | SHA-256 | Reviewed scope | +| --- | ---: | --- | --- | +| [project-guide.docx](project-guide.docx) | 45218 | `f8b0f4ed73dd19cd3d58991091df0519c93916d864c10f4b392ecbfd1f3372c1` | 5 pages, each viewed individually | + +Word review checked plain black titles, readable pagination, whole table rows, source references, practical limits and absence of clipping or overflow. Render receipts were matched to the current DOCX digest before approval. Workbook review inspected both tab previews and actual exported Table/autoFilter elements; recalculated success/failure summaries were compared independently with workflow metadata. Static previews do not draw Excel dropdown arrows; the exported workbook contains the actual filters. + +## Evidence and change boundary + +- Functional baseline: `43fd93f79043231230a4c19346bdb8a4c356d9ce`. +- Workflow observation: `2026-11-10T05:25:40.628667+00:00`; exact run URLs and source identities remain in [publications.json](publications.json). +- Local document-package validation verifies exact copied bytes, Office ZIP integrity, approved page/tab identities and internal documentation links. Repository-specific documentation and source-policy commands are run separately and recorded in the integration handoff. +- Source/index metadata is regenerated using the repository’s existing tools. Existing privacy, security, coverage and workflow gates are retained. +- PR and later main workflows must pass independently. This record does not claim future or unrun integration CI success. + +## Interpretation + +The Word files document the cited source; dated source reports retain their original execution scope. A passing workflow is distinct from completed analysis with zero findings, and neither establishes production suitability. The Excel source inventory is not a per-test execution report. Checksums identify exact bytes, not a signature or publisher attestation. + +Use the [handbook](../handbook.md) to choose usage, design, security and test documentation. Keep editable Markdown and reviewed editions together; do not replace historical measurements with undated claims. + +## Integration-local validation + +The exact copied Word package, current DOCX/render/page hashes, Office ZIP integrity, +source/workflow identities and handbook/report links passed independent checks. +`node scripts/generate-code-index.mjs --check` and +`node scripts/validate-repository.mjs` passed; `git diff --check` passed. +These documentation checks do not rerun native simulations or replace subsequent +PR and main CI. Runtime, user data, installed software and public releases are +unchanged. diff --git a/docs/reports/practical-workflows-20261109.md b/docs/reports/practical-workflows-20261109.md index 916dea2..bb1195c 100644 --- a/docs/reports/practical-workflows-20261109.md +++ b/docs/reports/practical-workflows-20261109.md @@ -8,27 +8,27 @@ matching. The optimized spatial query and independent quadratic reference apply their own inclusion predicates; World propagates body metadata unchanged. Drawing, position integration and boundary response stay independent of filtering. -Scene writers use v2; v1 remains readable with category1/all mask bits. Both filter +Scene writers use v2; v1 remains readable with category 1 / all mask bits. Both filter words belong to state hashing, intentionally changing old numeric fingerprints. The replay input format is unchanged. Unknown versions and bad/missing/negative/ overflowing filter fields remain errors. A v2 fuzz seed exercises the new grammar. ## Observed local evidence -- MSVC warning-as-error release build and10/10 native test groups passed. - 150 fixed-seed50-item scenes with varied masks/categories exactly match the +- MSVC warning-as-error release build and 10/10 native test groups passed. + 150 fixed-seed 50-item scenes with varied masks/categories exactly match the independent quadratic oracle. A hand matrix requires exactly player/character and player/zone matches; reverse ordering, bit31, zero masks, invalid categories, real World propagation, invalid-spawn atomicity and v1/v2 round trips are tested. -- Both actual CLI demonstrations completed360ticks. The five-entity filtered +- Both actual CLI demonstrations completed 360 ticks. The five-entity filtered example yielded exactly two initial pairs and zero final pairs; CSV rows list the correct category/mask values. Canonical scene, replay and PPM were produced. Initial/final are two snapshots, not collision episode/trajectory evidence. -- Existing20,000-entity benchmark passed unchanged budgets: storage1.267ms, - broadphase7.181ms, simulation4.651ms on this PC. Timings are not real-time claims. +- Existing 20,000-entity benchmark passed unchanged budgets: storage 1.267 ms, + broadphase 7.181 ms, simulation 4.651 ms on this PC. Timings are not real-time claims. - Formatting and generated source-index/repository checks passed. A native header/library/CMake-target install into a fresh project-local prefix passed. - Optional SDL3.4.16 frontend rebuilt from the existing pinned local source. + Optional SDL 3.4.16 frontend rebuilt from the existing pinned local source. Warning-denying Clang-tidy passed on all five changed implementation/test units; existing vendor-header warnings remained outside the configured user-code scope. Its first attempt lacked standard-library include paths; the identical policy @@ -40,10 +40,10 @@ overflowing filter fields remain errors. A v2 fuzz seed exercises the new gramma ## Limits -This is a fictional integer2D game-engine query feature, with no real-world +This is a fictional integer 2D game-engine query feature, with no real-world tracking, targeting, flight, physics calibration or weapon control. Filtering does not prevent bodies from passing through each other, apply forces or supply enter/exit trigger callbacks. Consumers own gameplay reactions and must pass currently valid handles to raw queries. State hashes are deterministic fingerprints, not cryptographic attestation. No user scenes, existing outputs or services were -deleted. Parent owns remote CI/publication; no Actions triggered here. +deleted. This dated local session did not execute hosted workflows; source-specific hosted results are linked separately in the documentation edition. diff --git a/docs/reports/project-guide.docx b/docs/reports/project-guide.docx new file mode 100644 index 0000000000000000000000000000000000000000..fe8a18c1be39153a7d4e544767fc9741534c0738 GIT binary patch literal 45218 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 literal 0 HcmV?d00001 diff --git a/docs/reports/publications.json b/docs/reports/publications.json new file mode 100644 index 0000000..bb59013 --- /dev/null +++ b/docs/reports/publications.json @@ -0,0 +1,59 @@ +{ + "schemaVersion": 1, + "project": "forge2d-engine", + "author": "Jason Stys", + "editionDate": "2026-11-09", + "sourceBaseline": "43fd93f79043231230a4c19346bdb8a4c356d9ce", + "sourceUrl": "https://github.com/JasonStys/forge2d-engine/tree/43fd93f79043231230a4c19346bdb8a4c356d9ce", + "functionalEvidenceBaseline": "43fd93f79043231230a4c19346bdb8a4c356d9ce", + "evidenceObservedAt": "2026-11-10T05:25:40.628667+00:00", + "workflowEvidence": [ + { + "conclusion": "success", + "databaseId": 42714064217, + "event": "push", + "headSha": "43fd93f79043231230a4c19346bdb8a4c356d9ce", + "name": "CI", + "status": "completed", + "url": "https://github.com/JasonStys/forge2d-engine/actions/runs/42714064217" + }, + { + "conclusion": "success", + "databaseId": 42714064589, + "event": "push", + "headSha": "43fd93f79043231230a4c19346bdb8a4c356d9ce", + "name": "CodeQL", + "status": "completed", + "url": "https://github.com/JasonStys/forge2d-engine/actions/runs/42714064589" + } + ], + "summary": "The implementation adds bidirectional collision category and mask filters, versioned scene migration, deterministic state hashes and initial/final overlap CSV inspection.", + "rationale": "Supports practical game-world collision layers and reproducible debugging against independent geometry oracles.", + "limitations": [ + "Category/mask filtering selects AABB query candidates; it does not add physical collision response, enter/exit callbacks or navigation changes.", + "Filter words change numeric state fingerprints even for legacy default filters; replay input grammar remains version 1.", + "Raw queries cannot establish current entity-generation validity; World owns lifetime checks. This is a fictional integer 2D game engine." + ], + "documents": [ + { + "filename": "project-guide.docx", + "mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "bytes": 45218, + "sha256": "f8b0f4ed73dd19cd3d58991091df0519c93916d864c10f4b392ecbfd1f3372c1", + "sourceBaseline": "43fd93f79043231230a4c19346bdb8a4c356d9ce", + "visualReview": { + "approved": true, + "method": "Every rendered page individually viewed at readable original resolution", + "pageCount": 5, + "renderedPageSha256": { + "page-1.png": "ed3d4acc6f5d060dfbbf0059d8b32fd40718cfab01df809fd302aaa5d73219e8", + "page-2.png": "69892ce958fb026019c2e321e984f8a13ec7541b7f0822caa2bd8cb48a9ea564", + "page-3.png": "ef62413c61cdc31de1e23d4c1cc29bd8c981a6288c99ea64e1c5cc5c8e830230", + "page-4.png": "db32dd727c0a38ed9920b60bfd22b32cc87b83421fd83565419fec1178e3a8b0", + "page-5.png": "46d3b7b19fd6fff5046c29d59c95b0a2a75983976541904288b815029c69b91c" + } + } + } + ], + "scope": "Reviewed documentation editions of the cited source. Checksums identify bytes, not authorship. Historical measurements retain their own dates; integration CI must be checked separately." +}