diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d14e88..f2aec59 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,22 @@ Initial release.
### Added
+- Welcome screen on launch: app title with three actions — New Capture
+ (creates a guide, opens the editor, and starts a capture session),
+ Existing Workspace (guide library), and Settings. The brand button
+ returns to the welcome screen from any view.
+
+### Fixed
+
+- Renderer scripts no longer collide in the shared global scope (the app
+ previously failed to boot with a blank window).
+- Focused-view toggle persists correctly (`step.focusedView.enabled`).
+- Annotation style edits no longer steal input focus on each keystroke.
+- Step list stays in sync after saves and undo/redo.
+- Escape deselects the active annotation instead of deleting it.
+
+### Added (initial feature set)
+
- Guide library with folders, favorites, title + full-text search, and a
quick-actions palette.
- Capture engine: full-screen / active-window / region capture, delay,
diff --git a/build/artifacts_manifest.json b/build/artifacts_manifest.json
new file mode 100644
index 0000000..f6e4ab3
--- /dev/null
+++ b/build/artifacts_manifest.json
@@ -0,0 +1,218 @@
+{
+ "format": "stepforge-artifacts-manifest",
+ "version": 1,
+ "generatedAt": "2026-06-11T02:33:30.203Z",
+ "packageVersion": "0.1.0",
+ "files": [
+ {
+ "kind": "artifact",
+ "path": "artifacts/stepforge_0.1.0_amd64.deb",
+ "size": 103679916,
+ "sha256": "e568d19b18dbd5be3f2bde1c3e6b70ce79243ba697d625e0a5c1af3e2bd9733e"
+ },
+ {
+ "kind": "artifact",
+ "path": "artifacts/stepforge_0.1.0_linux-x64.tar.gz",
+ "size": 139347926,
+ "sha256": "0bd6ea1d2c42b74e0b7411427f047dc8cbcc293507172b53ce43116e5f1affac"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/guide.json",
+ "size": 928,
+ "sha256": "1fcb87d79d7c8d187256dafdefdd065d3bb3e2fc3b76c52a6003e147213ec1ba"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-0997fb48-b598-4319-8144-0ceef68a84f4/step.json",
+ "size": 784,
+ "sha256": "e6233ff39c5ee5e869900fe2db3208443fc126b02aca1175412bc5ab28c767ae"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/original.png",
+ "size": 13643,
+ "sha256": "09e12f935511bb6fabb5637501aa7743516b96d990adfab62ccfa311a7b60606"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/step.json",
+ "size": 1609,
+ "sha256": "36048ccb6e30c00d6b652a0959f794c841ba3b11ff2ba1d6d2afcc94eeed6634"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/working.png",
+ "size": 13643,
+ "sha256": "09e12f935511bb6fabb5637501aa7743516b96d990adfab62ccfa311a7b60606"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-62da8044-c236-4012-9fce-15785c94bfa7/step.json",
+ "size": 547,
+ "sha256": "243b7b1d9e9697dce03eb5b80254fe898835f2f7a89c287e3a6d6cd305f660b9"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/original.png",
+ "size": 13602,
+ "sha256": "c96eedffdc5fd2eb9b63942cc00f1c8a91d01a0c5c2316c1d12d750b9b49e3d0"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/step.json",
+ "size": 1975,
+ "sha256": "32ee15cec46e2ce8c9fe289ab9848c461978bf3d3ff0625fbaf8c4958575e573"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/working.png",
+ "size": 13602,
+ "sha256": "c96eedffdc5fd2eb9b63942cc00f1c8a91d01a0c5c2316c1d12d750b9b49e3d0"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/original.png",
+ "size": 14031,
+ "sha256": "b5e93a0ee74e2bdbbdf0871e901726dfbdc8b45dd648c959743520f92b02e7a2"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/step.json",
+ "size": 1886,
+ "sha256": "e707642d9fb4c2079075615836b26834cc1c053b6b2fb7eec0dc0b40029db614"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/working.png",
+ "size": 14031,
+ "sha256": "b5e93a0ee74e2bdbbdf0871e901726dfbdc8b45dd648c959743520f92b02e7a2"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-c0addd40-3e96-495f-b196-d49c08518dba/step.json",
+ "size": 521,
+ "sha256": "3d89cd70a5294a4166d60e20b0d19408a834c31415e4319839577a8b18ccbce3"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/docx/reset-a-password-in-admin-portal.docx",
+ "size": 110463,
+ "sha256": "be9e2b550b732fc6cd4a171b72749b49fe67730ee9969f69c23175688b0bea14"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/gif/reset-a-password-in-admin-portal.gif",
+ "size": 32090,
+ "sha256": "70a789c6ce1aa6154c65d0ee88a286d888fdfd9fd5c3045a14242e13df5ca263"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/html-rich/reset-a-password-in-admin-portal-rich.html",
+ "size": 149943,
+ "sha256": "9a449f2507f6f4b43d67589cb2f4f28682d8f6fdec15cc0541b26a81624a528b"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/html-simple/reset-a-password-in-admin-portal.html",
+ "size": 146646,
+ "sha256": "5cababe0b51a3590d3ceee4179760e0c2179e9ed340d85e1b65253e4275bb9d0"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/image-bundle/reset-a-password-in-admin-portal-bundle.json",
+ "size": 779,
+ "sha256": "24bae92a7d627ad65d9cea906f840fcfd46e44aa263ab927774daa49fef60f45"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png",
+ "size": 31424,
+ "sha256": "892a3174e9876ebfab4c879d6d579cf8ad6eba2f299ad95feff33adaf205e042"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png",
+ "size": 38991,
+ "sha256": "f1c79fb2baa1ef41dd85b04be59cc796f3822858654612044a22e27f20d0696a"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png",
+ "size": 37274,
+ "sha256": "32c5e15f8a04d6af01b7d139cff732872d5ce7e3e519be6ece99cca4167856ed"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/json/reset-a-password-in-admin-portal.json",
+ "size": 6740,
+ "sha256": "7257af7b3df168df9656159f84e0f7b538437775dc2e716e7f87d00dd9d40efd"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/json/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png",
+ "size": 31424,
+ "sha256": "892a3174e9876ebfab4c879d6d579cf8ad6eba2f299ad95feff33adaf205e042"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/json/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png",
+ "size": 38991,
+ "sha256": "f1c79fb2baa1ef41dd85b04be59cc796f3822858654612044a22e27f20d0696a"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/json/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png",
+ "size": 37274,
+ "sha256": "32c5e15f8a04d6af01b7d139cff732872d5ce7e3e519be6ece99cca4167856ed"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/markdown/reset-a-password-in-admin-portal.md",
+ "size": 1186,
+ "sha256": "16bbd2eb8850d8a55914abe9ece4d2aee465820fcd6c5ffde8925f37dd2b115b"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png",
+ "size": 31424,
+ "sha256": "892a3174e9876ebfab4c879d6d579cf8ad6eba2f299ad95feff33adaf205e042"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png",
+ "size": 38991,
+ "sha256": "f1c79fb2baa1ef41dd85b04be59cc796f3822858654612044a22e27f20d0696a"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png",
+ "size": 37274,
+ "sha256": "32c5e15f8a04d6af01b7d139cff732872d5ce7e3e519be6ece99cca4167856ed"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/pdf/reset-a-password-in-admin-portal.pdf",
+ "size": 103120,
+ "sha256": "58a952a2f95653a91d4e662e4bc2ddcb0177de33e51a8f9e454cdf158ba3a795"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-exports/pptx/reset-a-password-in-admin-portal.pptx",
+ "size": 117643,
+ "sha256": "4ce1e82903b726c549e53235e3fd4c70cf647123ccd823052030e2e1b9449864"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-guide.sfgz",
+ "size": 88967,
+ "sha256": "4c36ae2ee22ca8da9fc066efaed72dc19084f8655b10162deb1528e2ebb3a0bf"
+ },
+ {
+ "kind": "sample",
+ "path": "../examples/sample-manifest.json",
+ "size": 1186,
+ "sha256": "2cecfc8eaef1a6b87aeac4692b6a22d2c6d81b533b18b15bc87db1bc3774b007"
+ }
+ ]
+}
diff --git a/build/build_report.md b/build/build_report.md
new file mode 100644
index 0000000..7f53150
--- /dev/null
+++ b/build/build_report.md
@@ -0,0 +1,43 @@
+# StepForge Build Report
+
+Version: 0.1.0
+Generated: 2026-06-11T02:33:30.201Z
+Host: linux x64 (node v20.20.2)
+
+## Outputs
+
+- Portable tarball: artifacts/stepforge_0.1.0_linux-x64.tar.gz
+- Debian package: artifacts/stepforge_0.1.0_amd64.deb
+- Sample guide archive: ../examples/sample-guide.sfgz
+- Sample exports (9 formats): see examples/sample-exports/
+- Full artifact list with sha256 checksums: artifacts_manifest.json
+
+## Packaging tool availability
+
+| Tool | Status |
+|---|---|
+| dpkg-deb (Linux .deb) | available |
+| rpmbuild (Linux .rpm) | **missing** |
+| appimagetool (Linux AppImage) | **missing** |
+| makensis (Windows installer .exe) | **missing** |
+| wixl / WiX (Windows .msi) | **missing** |
+
+Fallback policy: when a packaging tool is missing the build still produces
+the runnable app (portable tarball with launcher) plus whatever package
+formats the available tools allow. Windows artifacts are produced by
+`npm run package:windows` (electron-builder, portable .exe); .msi/.rpm/
+AppImage require the tools listed above and are skipped on this host.
+
+## Offline guarantee
+
+- The shipped app opens no sockets: no telemetry, update checks, license
+ checks, cloud sync, or remote AI. See SECURITY.md.
+- All exporters (PNG/GIF/PDF/DOCX/PPTX/ZIP) are implemented in-repo with
+ Node built-ins; Electron is the only third-party dependency
+ (dev-time fetch recorded in build/agent_audit.md).
+
+## Verification
+
+- `bash tests/run_test.sh` runs the workflow suites (node --test), a
+ startup smoke test of the Electron launcher, the sample-artifact
+ pipeline, and this release build.
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/guide.json b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/guide.json
new file mode 100644
index 0000000..89025da
--- /dev/null
+++ b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/guide.json
@@ -0,0 +1,29 @@
+{
+ "schemaVersion": 1,
+ "guideId": "guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f",
+ "title": "Reset a password in Admin Portal",
+ "descriptionHtml": "
Offline sample guide showing capture, annotations, rich text, and exports.
",
+ "placeholders": {
+ "Product": "Admin Portal",
+ "Author": "StepForge",
+ "Department": "Support"
+ },
+ "flags": {
+ "focusedViewDefault": true,
+ "hideSkippedStepsInExports": true
+ },
+ "themeOverride": "system",
+ "createdAt": "2026-06-11T02:32:07Z",
+ "updatedAt": "2026-06-11T02:32:07Z",
+ "stepsOrder": [
+ "step-592cde3d-19e2-441a-a19b-53ccd4ac132c",
+ "step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48",
+ "step-0997fb48-b598-4319-8144-0ceef68a84f4",
+ "step-8a33be62-08c7-4a5d-ab9d-9f415269d015",
+ "step-c0addd40-3e96-495f-b196-d49c08518dba",
+ "step-62da8044-c236-4012-9fce-15785c94bfa7"
+ ],
+ "favorite": false,
+ "linkedSource": null,
+ "exportProfiles": {}
+}
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-0997fb48-b598-4319-8144-0ceef68a84f4/step.json b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-0997fb48-b598-4319-8144-0ceef68a84f4/step.json
new file mode 100644
index 0000000..6c7ad9d
--- /dev/null
+++ b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-0997fb48-b598-4319-8144-0ceef68a84f4/step.json
@@ -0,0 +1,32 @@
+{
+ "stepId": "step-0997fb48-b598-4319-8144-0ceef68a84f4",
+ "parentStepId": "step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48",
+ "kind": "empty",
+ "status": "todo",
+ "title": "Confirm permission prompt",
+ "descriptionHtml": "Only administrators can complete this step.
",
+ "hidden": false,
+ "skipped": false,
+ "forceNewPage": false,
+ "focusedView": {
+ "enabled": false,
+ "zoom": 1,
+ "panX": 0.5,
+ "panY": 0.5
+ },
+ "image": null,
+ "extraImages": [],
+ "annotations": [],
+ "textBlocks": [
+ {
+ "id": "tb-e3aa7982-3eb4-4db1-a1af-fda7c72b46aa",
+ "position": "after-description",
+ "level": "warn",
+ "title": "Access",
+ "descriptionHtml": "Admin rights required.
"
+ }
+ ],
+ "codeBlocks": [],
+ "tableBlocks": [],
+ "links": []
+}
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/original.png b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/original.png
new file mode 100644
index 0000000..8478071
Binary files /dev/null and b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/original.png differ
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/step.json b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/step.json
new file mode 100644
index 0000000..a15de68
--- /dev/null
+++ b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/step.json
@@ -0,0 +1,73 @@
+{
+ "stepId": "step-592cde3d-19e2-441a-a19b-53ccd4ac132c",
+ "parentStepId": null,
+ "kind": "image",
+ "status": "todo",
+ "title": "Open [[Product]] users",
+ "descriptionHtml": "Open the users list and select the target account.
",
+ "hidden": false,
+ "skipped": false,
+ "forceNewPage": false,
+ "focusedView": {
+ "enabled": true,
+ "zoom": 1.1,
+ "panX": 0.5,
+ "panY": 0.5
+ },
+ "image": {
+ "originalPath": "original.png",
+ "workingPath": "working.png",
+ "size": {
+ "width": 1280,
+ "height": 760
+ }
+ },
+ "extraImages": [],
+ "annotations": [
+ {
+ "id": "ann-54403181-b784-4d9b-9285-b9504a7c2f8d",
+ "type": "rect",
+ "x": 0.275,
+ "y": 0.18,
+ "w": 0.19,
+ "h": 0.18,
+ "text": "",
+ "style": {
+ "stroke": "#0068ff",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 6,
+ "fontSize": 0.022
+ }
+ },
+ {
+ "id": "ann-303a7cdc-4866-4667-8046-33ba7bfb8687",
+ "type": "number",
+ "x": 0.3,
+ "y": 0.08,
+ "w": 0.08,
+ "h": 0.12,
+ "text": "",
+ "style": {
+ "stroke": "#0068ff",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 3,
+ "fontSize": 0.022
+ },
+ "value": 1
+ }
+ ],
+ "textBlocks": [
+ {
+ "id": "tb-69f3f373-12e6-4ecf-b93c-36f3b770bece",
+ "position": "after-description",
+ "level": "info",
+ "title": "Tip",
+ "descriptionHtml": "Use the search box to avoid scrolling.
"
+ }
+ ],
+ "codeBlocks": [],
+ "tableBlocks": [],
+ "links": []
+}
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/working.png b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/working.png
new file mode 100644
index 0000000..8478071
Binary files /dev/null and b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-592cde3d-19e2-441a-a19b-53ccd4ac132c/working.png differ
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-62da8044-c236-4012-9fce-15785c94bfa7/step.json b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-62da8044-c236-4012-9fce-15785c94bfa7/step.json
new file mode 100644
index 0000000..f601956
--- /dev/null
+++ b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-62da8044-c236-4012-9fce-15785c94bfa7/step.json
@@ -0,0 +1,24 @@
+{
+ "stepId": "step-62da8044-c236-4012-9fce-15785c94bfa7",
+ "parentStepId": null,
+ "kind": "empty",
+ "status": "todo",
+ "title": "Deprecated flow",
+ "descriptionHtml": "This skipped step remains in the library but is excluded from exports.
",
+ "hidden": false,
+ "skipped": true,
+ "forceNewPage": false,
+ "focusedView": {
+ "enabled": false,
+ "zoom": 1,
+ "panX": 0.5,
+ "panY": 0.5
+ },
+ "image": null,
+ "extraImages": [],
+ "annotations": [],
+ "textBlocks": [],
+ "codeBlocks": [],
+ "tableBlocks": [],
+ "links": []
+}
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/original.png b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/original.png
new file mode 100644
index 0000000..64693bb
Binary files /dev/null and b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/original.png differ
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/step.json b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/step.json
new file mode 100644
index 0000000..262bc97
--- /dev/null
+++ b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/step.json
@@ -0,0 +1,100 @@
+{
+ "stepId": "step-8a33be62-08c7-4a5d-ab9d-9f415269d015",
+ "parentStepId": null,
+ "kind": "image",
+ "status": "todo",
+ "title": "Review the confirmation",
+ "descriptionHtml": "Confirm the summary and close the modal.
",
+ "hidden": false,
+ "skipped": false,
+ "forceNewPage": false,
+ "focusedView": {
+ "enabled": true,
+ "zoom": 1.1,
+ "panX": 0.5,
+ "panY": 0.5
+ },
+ "image": {
+ "originalPath": "original.png",
+ "workingPath": "working.png",
+ "size": {
+ "width": 1280,
+ "height": 760
+ }
+ },
+ "extraImages": [],
+ "annotations": [
+ {
+ "id": "ann-281ebcd6-e0e3-4304-9232-ee25353e2321",
+ "type": "blur",
+ "x": 0.49,
+ "y": 0.32,
+ "w": 0.21,
+ "h": 0.08,
+ "text": "",
+ "style": {
+ "stroke": "#9ca3af",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 2,
+ "fontSize": 0.022
+ },
+ "radius": 12
+ },
+ {
+ "id": "ann-6224b838-a39d-4fae-9b68-6a4f2f8af60d",
+ "type": "highlight",
+ "x": 0.47,
+ "y": 0.24,
+ "w": 0.28,
+ "h": 0.2,
+ "text": "",
+ "style": {
+ "stroke": "#f0a500",
+ "fill": "#ffeeb0",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 2,
+ "fontSize": 0.022
+ }
+ },
+ {
+ "id": "ann-6dd50b00-6f29-431b-bee0-c217032af1a4",
+ "type": "number",
+ "x": 0.31,
+ "y": 0.08,
+ "w": 0.08,
+ "h": 0.12,
+ "text": "",
+ "style": {
+ "stroke": "#36a",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 3,
+ "fontSize": 0.022
+ },
+ "value": 3
+ }
+ ],
+ "textBlocks": [],
+ "codeBlocks": [],
+ "tableBlocks": [
+ {
+ "id": "t1",
+ "rows": [
+ [
+ "Field",
+ "Value"
+ ],
+ [
+ "Title",
+ "Admin Portal"
+ ],
+ [
+ "Owner",
+ "Support"
+ ]
+ ]
+ }
+ ],
+ "links": []
+}
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/working.png b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/working.png
new file mode 100644
index 0000000..64693bb
Binary files /dev/null and b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-8a33be62-08c7-4a5d-ab9d-9f415269d015/working.png differ
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/original.png b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/original.png
new file mode 100644
index 0000000..621101a
Binary files /dev/null and b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/original.png differ
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/step.json b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/step.json
new file mode 100644
index 0000000..a908709
--- /dev/null
+++ b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/step.json
@@ -0,0 +1,88 @@
+{
+ "stepId": "step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48",
+ "parentStepId": null,
+ "kind": "image",
+ "status": "todo",
+ "title": "Enable the reset policy",
+ "descriptionHtml": "Make sure the policy is active before continuing.
",
+ "hidden": false,
+ "skipped": false,
+ "forceNewPage": false,
+ "focusedView": {
+ "enabled": true,
+ "zoom": 1.1,
+ "panX": 0.5,
+ "panY": 0.5
+ },
+ "image": {
+ "originalPath": "original.png",
+ "workingPath": "working.png",
+ "size": {
+ "width": 1280,
+ "height": 760
+ }
+ },
+ "extraImages": [],
+ "annotations": [
+ {
+ "id": "ann-80ff688a-e1ca-46e7-9519-0dd38240d9c3",
+ "type": "arrow",
+ "x": 0.47,
+ "y": 0.24,
+ "w": 0.23,
+ "h": -0.04,
+ "text": "",
+ "style": {
+ "stroke": "#14a375",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 5,
+ "fontSize": 0.022
+ }
+ },
+ {
+ "id": "ann-bd413182-4146-448b-95f8-72630f55437d",
+ "type": "tooltip",
+ "x": 0.53,
+ "y": 0.13,
+ "w": 0.17,
+ "h": 0.08,
+ "text": "Primary action",
+ "style": {
+ "stroke": "#111827",
+ "fill": "#111827",
+ "textColor": "#ffffff",
+ "strokeWidth": 3,
+ "fontSize": 0.022,
+ "tail": "bottom"
+ }
+ },
+ {
+ "id": "ann-537b3971-6361-4763-8424-da8980479507",
+ "type": "number",
+ "x": 0.31,
+ "y": 0.08,
+ "w": 0.08,
+ "h": 0.12,
+ "text": "",
+ "style": {
+ "stroke": "#14a375",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 3,
+ "fontSize": 0.022
+ },
+ "value": 2
+ }
+ ],
+ "textBlocks": [],
+ "codeBlocks": [
+ {
+ "id": "cmd",
+ "language": "bash",
+ "code": "stepforge --capture --window --delay 300"
+ }
+ ],
+ "tableBlocks": [],
+ "links": []
+}
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/working.png b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/working.png
new file mode 100644
index 0000000..621101a
Binary files /dev/null and b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-bf6e1f92-47c8-478b-ba42-d2a3fe93bc48/working.png differ
diff --git a/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-c0addd40-3e96-495f-b196-d49c08518dba/step.json b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-c0addd40-3e96-495f-b196-d49c08518dba/step.json
new file mode 100644
index 0000000..f894a99
--- /dev/null
+++ b/examples/sample-data/library/guides/guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f/steps/step-c0addd40-3e96-495f-b196-d49c08518dba/step.json
@@ -0,0 +1,24 @@
+{
+ "stepId": "step-c0addd40-3e96-495f-b196-d49c08518dba",
+ "parentStepId": null,
+ "kind": "empty",
+ "status": "todo",
+ "title": "Legacy note",
+ "descriptionHtml": "This hidden step exercises filtering in exports.
",
+ "hidden": true,
+ "skipped": false,
+ "forceNewPage": false,
+ "focusedView": {
+ "enabled": false,
+ "zoom": 1,
+ "panX": 0.5,
+ "panY": 0.5
+ },
+ "image": null,
+ "extraImages": [],
+ "annotations": [],
+ "textBlocks": [],
+ "codeBlocks": [],
+ "tableBlocks": [],
+ "links": []
+}
diff --git a/examples/sample-exports/docx/reset-a-password-in-admin-portal.docx b/examples/sample-exports/docx/reset-a-password-in-admin-portal.docx
new file mode 100644
index 0000000..705aa26
Binary files /dev/null and b/examples/sample-exports/docx/reset-a-password-in-admin-portal.docx differ
diff --git a/examples/sample-exports/gif/reset-a-password-in-admin-portal.gif b/examples/sample-exports/gif/reset-a-password-in-admin-portal.gif
new file mode 100644
index 0000000..6a515a5
Binary files /dev/null and b/examples/sample-exports/gif/reset-a-password-in-admin-portal.gif differ
diff --git a/examples/sample-exports/html-rich/reset-a-password-in-admin-portal-rich.html b/examples/sample-exports/html-rich/reset-a-password-in-admin-portal-rich.html
new file mode 100644
index 0000000..2084fa1
--- /dev/null
+++ b/examples/sample-exports/html-rich/reset-a-password-in-admin-portal-rich.html
@@ -0,0 +1,130 @@
+
+
+
+
+
+Reset a password in Admin Portal
+
+
+
+
+
+
+Reset a password in Admin Portal
+Offline sample guide showing capture, annotations, rich text, and exports.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/sample-exports/html-simple/reset-a-password-in-admin-portal.html b/examples/sample-exports/html-simple/reset-a-password-in-admin-portal.html
new file mode 100644
index 0000000..3c0f3f8
--- /dev/null
+++ b/examples/sample-exports/html-simple/reset-a-password-in-admin-portal.html
@@ -0,0 +1,61 @@
+
+
+
+
+
+Reset a password in Admin Portal
+
+
+
+Reset a password in Admin Portal
+Offline sample guide showing capture, annotations, rich text, and exports.
+
+
+ 1. Open Admin Portal users
+ Open the users list and select the target account.
+
+Note: TipUse the search box to avoid scrolling.
+
+
+
+ 2. Enable the reset policy
+ Make sure the policy is active before continuing.
+
+stepforge --capture --window --delay 300
+
+
+
+ 2.1. Confirm permission prompt
+ Only administrators can complete this step.
+
+
+
+
+ 3. Review the confirmation
+ Confirm the summary and close the modal.
+
+| Field | Value |
|---|
| Title | Admin Portal |
| Owner | Support |
+
+
+
+
diff --git a/examples/sample-exports/image-bundle/reset-a-password-in-admin-portal-bundle.json b/examples/sample-exports/image-bundle/reset-a-password-in-admin-portal-bundle.json
new file mode 100644
index 0000000..badf226
--- /dev/null
+++ b/examples/sample-exports/image-bundle/reset-a-password-in-admin-portal-bundle.json
@@ -0,0 +1,30 @@
+{
+ "format": "stepforge-image-bundle",
+ "version": 1,
+ "guide": {
+ "title": "Reset a password in Admin Portal",
+ "generatedAt": "2026-06-11T02:32:07.575Z"
+ },
+ "steps": [
+ {
+ "number": "1",
+ "title": "Open Admin Portal users",
+ "image": "steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png"
+ },
+ {
+ "number": "2",
+ "title": "Enable the reset policy",
+ "image": "steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png"
+ },
+ {
+ "number": "2.1",
+ "title": "Confirm permission prompt",
+ "image": null
+ },
+ {
+ "number": "3",
+ "title": "Review the confirmation",
+ "image": "steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png"
+ }
+ ]
+}
diff --git a/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png b/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png
new file mode 100644
index 0000000..03df130
Binary files /dev/null and b/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png differ
diff --git a/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png b/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png
new file mode 100644
index 0000000..39f54c7
Binary files /dev/null and b/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png differ
diff --git a/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png b/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png
new file mode 100644
index 0000000..2a56a9b
Binary files /dev/null and b/examples/sample-exports/image-bundle/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png differ
diff --git a/examples/sample-exports/json/reset-a-password-in-admin-portal.json b/examples/sample-exports/json/reset-a-password-in-admin-portal.json
new file mode 100644
index 0000000..3ad9fa7
--- /dev/null
+++ b/examples/sample-exports/json/reset-a-password-in-admin-portal.json
@@ -0,0 +1,255 @@
+{
+ "format": "stepforge-guide",
+ "version": 1,
+ "generatedAt": "2026-06-11T02:32:07.575Z",
+ "guide": {
+ "title": "Reset a password in Admin Portal",
+ "descriptionHtml": "Offline sample guide showing capture, annotations, rich text, and exports.
",
+ "createdAt": "2026-06-11T02:32:07Z",
+ "updatedAt": "2026-06-11T02:32:07Z"
+ },
+ "steps": [
+ {
+ "number": "1",
+ "kind": "image",
+ "status": "todo",
+ "title": "Open Admin Portal users",
+ "descriptionHtml": "Open the users list and select the target account.
",
+ "descriptionText": "Open the users list and select the target account.",
+ "image": {
+ "relPath": "steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png",
+ "width": 1280,
+ "height": 760
+ },
+ "annotations": [
+ {
+ "id": "ann-54403181-b784-4d9b-9285-b9504a7c2f8d",
+ "type": "rect",
+ "x": 0.275,
+ "y": 0.18,
+ "w": 0.19,
+ "h": 0.18,
+ "text": "",
+ "style": {
+ "stroke": "#0068ff",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 6,
+ "fontSize": 0.022
+ }
+ },
+ {
+ "id": "ann-303a7cdc-4866-4667-8046-33ba7bfb8687",
+ "type": "number",
+ "x": 0.3,
+ "y": 0.08,
+ "w": 0.08,
+ "h": 0.12,
+ "text": "",
+ "style": {
+ "stroke": "#0068ff",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 3,
+ "fontSize": 0.022
+ },
+ "value": 1
+ }
+ ],
+ "textBlocks": [
+ {
+ "position": "after-description",
+ "level": "info",
+ "title": "Tip",
+ "descriptionHtml": "Use the search box to avoid scrolling.
"
+ }
+ ],
+ "codeBlocks": [],
+ "tableBlocks": [],
+ "links": []
+ },
+ {
+ "number": "2",
+ "kind": "image",
+ "status": "todo",
+ "title": "Enable the reset policy",
+ "descriptionHtml": "Make sure the policy is active before continuing.
",
+ "descriptionText": "Make sure the policy is active before continuing.",
+ "image": {
+ "relPath": "steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png",
+ "width": 1280,
+ "height": 760
+ },
+ "annotations": [
+ {
+ "id": "ann-80ff688a-e1ca-46e7-9519-0dd38240d9c3",
+ "type": "arrow",
+ "x": 0.47,
+ "y": 0.24,
+ "w": 0.23,
+ "h": -0.04,
+ "text": "",
+ "style": {
+ "stroke": "#14a375",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 5,
+ "fontSize": 0.022
+ }
+ },
+ {
+ "id": "ann-bd413182-4146-448b-95f8-72630f55437d",
+ "type": "tooltip",
+ "x": 0.53,
+ "y": 0.13,
+ "w": 0.17,
+ "h": 0.08,
+ "text": "Primary action",
+ "style": {
+ "stroke": "#111827",
+ "fill": "#111827",
+ "textColor": "#ffffff",
+ "strokeWidth": 3,
+ "fontSize": 0.022,
+ "tail": "bottom"
+ }
+ },
+ {
+ "id": "ann-537b3971-6361-4763-8424-da8980479507",
+ "type": "number",
+ "x": 0.31,
+ "y": 0.08,
+ "w": 0.08,
+ "h": 0.12,
+ "text": "",
+ "style": {
+ "stroke": "#14a375",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 3,
+ "fontSize": 0.022
+ },
+ "value": 2
+ }
+ ],
+ "textBlocks": [],
+ "codeBlocks": [
+ {
+ "id": "cmd",
+ "language": "bash",
+ "code": "stepforge --capture --window --delay 300"
+ }
+ ],
+ "tableBlocks": [],
+ "links": []
+ },
+ {
+ "number": "2.1",
+ "kind": "empty",
+ "status": "todo",
+ "title": "Confirm permission prompt",
+ "descriptionHtml": "Only administrators can complete this step.
",
+ "descriptionText": "Only administrators can complete this step.",
+ "image": null,
+ "annotations": [],
+ "textBlocks": [
+ {
+ "position": "after-description",
+ "level": "warn",
+ "title": "Access",
+ "descriptionHtml": "Admin rights required.
"
+ }
+ ],
+ "codeBlocks": [],
+ "tableBlocks": [],
+ "links": []
+ },
+ {
+ "number": "3",
+ "kind": "image",
+ "status": "todo",
+ "title": "Review the confirmation",
+ "descriptionHtml": "Confirm the summary and close the modal.
",
+ "descriptionText": "Confirm the summary and close the modal.",
+ "image": {
+ "relPath": "steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png",
+ "width": 1280,
+ "height": 760
+ },
+ "annotations": [
+ {
+ "id": "ann-281ebcd6-e0e3-4304-9232-ee25353e2321",
+ "type": "blur",
+ "x": 0.49,
+ "y": 0.32,
+ "w": 0.21,
+ "h": 0.08,
+ "text": "",
+ "style": {
+ "stroke": "#9ca3af",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 2,
+ "fontSize": 0.022
+ },
+ "radius": 12
+ },
+ {
+ "id": "ann-6224b838-a39d-4fae-9b68-6a4f2f8af60d",
+ "type": "highlight",
+ "x": 0.47,
+ "y": 0.24,
+ "w": 0.28,
+ "h": 0.2,
+ "text": "",
+ "style": {
+ "stroke": "#f0a500",
+ "fill": "#ffeeb0",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 2,
+ "fontSize": 0.022
+ }
+ },
+ {
+ "id": "ann-6dd50b00-6f29-431b-bee0-c217032af1a4",
+ "type": "number",
+ "x": 0.31,
+ "y": 0.08,
+ "w": 0.08,
+ "h": 0.12,
+ "text": "",
+ "style": {
+ "stroke": "#36a",
+ "fill": "transparent",
+ "textColor": "#FFFFFF",
+ "strokeWidth": 3,
+ "fontSize": 0.022
+ },
+ "value": 3
+ }
+ ],
+ "textBlocks": [],
+ "codeBlocks": [],
+ "tableBlocks": [
+ {
+ "id": "t1",
+ "rows": [
+ [
+ "Field",
+ "Value"
+ ],
+ [
+ "Title",
+ "Admin Portal"
+ ],
+ [
+ "Owner",
+ "Support"
+ ]
+ ]
+ }
+ ],
+ "links": []
+ }
+ ]
+}
diff --git a/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png b/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png
new file mode 100644
index 0000000..03df130
Binary files /dev/null and b/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png differ
diff --git a/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png b/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png
new file mode 100644
index 0000000..39f54c7
Binary files /dev/null and b/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png differ
diff --git a/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png b/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png
new file mode 100644
index 0000000..2a56a9b
Binary files /dev/null and b/examples/sample-exports/json/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png differ
diff --git a/examples/sample-exports/markdown/reset-a-password-in-admin-portal.md b/examples/sample-exports/markdown/reset-a-password-in-admin-portal.md
new file mode 100644
index 0000000..24d8773
--- /dev/null
+++ b/examples/sample-exports/markdown/reset-a-password-in-admin-portal.md
@@ -0,0 +1,56 @@
+# Reset a password in Admin Portal
+
+Offline sample guide showing capture, annotations, rich text, and exports.
+
+## Contents
+
+- [1. Open Admin Portal users](#step-1)
+- [2. Enable the reset policy](#step-2)
+ - [2.1. Confirm permission prompt](#step-2-1)
+- [3. Review the confirmation](#step-3)
+
+
+
+## 1. Open Admin Portal users
+
+Open the users list and select the target account.
+
+
+
+> **Note: Tip**
+> Use the search box to avoid scrolling.
+
+
+
+## 2. Enable the reset policy
+
+Make sure the policy is active before continuing.
+
+
+
+```bash
+stepforge --capture --window --delay 300
+```
+
+
+
+### 2.1. Confirm permission prompt
+
+Only administrators can complete this step.
+
+> **Warning: Access**
+> Admin rights required.
+
+
+
+## 3. Review the confirmation
+
+Confirm the summary and close the modal.
+
+
+
+| Field | Value |
+| --- | --- |
+| Title | Admin Portal |
+| Owner | Support |
+
diff --git a/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png b/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png
new file mode 100644
index 0000000..03df130
Binary files /dev/null and b/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/001-open-admin-portal-users.png differ
diff --git a/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png b/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png
new file mode 100644
index 0000000..39f54c7
Binary files /dev/null and b/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/002-enable-the-reset-policy.png differ
diff --git a/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png b/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png
new file mode 100644
index 0000000..2a56a9b
Binary files /dev/null and b/examples/sample-exports/markdown/steps-reset-a-password-in-admin-portal/004-review-the-confirmation.png differ
diff --git a/examples/sample-exports/pdf/reset-a-password-in-admin-portal.pdf b/examples/sample-exports/pdf/reset-a-password-in-admin-portal.pdf
new file mode 100644
index 0000000..da5d519
Binary files /dev/null and b/examples/sample-exports/pdf/reset-a-password-in-admin-portal.pdf differ
diff --git a/examples/sample-exports/pptx/reset-a-password-in-admin-portal.pptx b/examples/sample-exports/pptx/reset-a-password-in-admin-portal.pptx
new file mode 100644
index 0000000..43a77d1
Binary files /dev/null and b/examples/sample-exports/pptx/reset-a-password-in-admin-portal.pptx differ
diff --git a/examples/sample-guide.sfgz b/examples/sample-guide.sfgz
new file mode 100644
index 0000000..512195e
Binary files /dev/null and b/examples/sample-guide.sfgz differ
diff --git a/examples/sample-manifest.json b/examples/sample-manifest.json
new file mode 100644
index 0000000..09b3291
--- /dev/null
+++ b/examples/sample-manifest.json
@@ -0,0 +1,23 @@
+{
+ "format": "stepforge-sample-manifest",
+ "version": 1,
+ "generatedAt": "2026-06-11T02:32:07.575Z",
+ "guideId": "guide-319c9f4d-4fa5-4399-81b5-258cc3393e1f",
+ "title": "Reset a password in Admin Portal",
+ "dataDir": "sample-data",
+ "note": "The sample guide is generated entirely offline from local assets.",
+ "archive": "sample-guide.sfgz",
+ "exports": {
+ "json": "sample-exports/json/reset-a-password-in-admin-portal.json",
+ "markdown": "sample-exports/markdown/reset-a-password-in-admin-portal.md",
+ "html-simple": "sample-exports/html-simple/reset-a-password-in-admin-portal.html",
+ "html-rich": "sample-exports/html-rich/reset-a-password-in-admin-portal-rich.html",
+ "pdf": "sample-exports/pdf/reset-a-password-in-admin-portal.pdf",
+ "gif": "sample-exports/gif/reset-a-password-in-admin-portal.gif",
+ "image-bundle": "sample-exports/image-bundle/reset-a-password-in-admin-portal-bundle.json",
+ "docx": "sample-exports/docx/reset-a-password-in-admin-portal.docx",
+ "pptx": "sample-exports/pptx/reset-a-password-in-admin-portal.pptx"
+ },
+ "substepId": "step-0997fb48-b598-4319-8144-0ceef68a84f4",
+ "slug": "reset-a-password-in-admin-portal"
+}
diff --git a/scripts/build-release.sh b/scripts/build-release.sh
index 76767bb..7b14707 100644
--- a/scripts/build-release.sh
+++ b/scripts/build-release.sh
@@ -70,22 +70,61 @@ for (const rel of walk(examplesRoot, examplesRoot)) {
}
const pkg = require(path.join(rootDir, 'package.json'));
+
+const { execSync } = require('node:child_process');
+function toolAvailable(cmd) {
+ try { execSync(`command -v ${cmd}`, { stdio: 'pipe', shell: '/bin/bash' }); return true; } catch { return false; }
+}
+const tools = {
+ 'dpkg-deb (Linux .deb)': toolAvailable('dpkg-deb'),
+ 'rpmbuild (Linux .rpm)': toolAvailable('rpmbuild'),
+ 'appimagetool (Linux AppImage)': toolAvailable('appimagetool'),
+ 'makensis (Windows installer .exe)': toolAvailable('makensis'),
+ 'wixl / WiX (Windows .msi)': toolAvailable('wixl'),
+};
+const toolRows = Object.entries(tools)
+ .map(([name, ok]) => `| ${name} | ${ok ? 'available' : '**missing**'} |`)
+ .join('\n');
+
const report = `# StepForge Build Report
Version: ${pkg.version}
Generated: ${new Date().toISOString()}
+Host: ${process.platform} ${process.arch} (node ${process.version})
## Outputs
- Portable tarball: ${files.find((f) => f.path.endsWith('.tar.gz'))?.path || 'not generated'}
- Debian package: ${files.find((f) => f.path.endsWith('.deb'))?.path || 'not generated'}
- Sample guide archive: ${files.find((f) => f.path.endsWith('sample-guide.sfgz'))?.path || 'not generated'}
+- Sample exports (9 formats): see examples/sample-exports/
+- Full artifact list with sha256 checksums: artifacts_manifest.json
-## Notes
+## Packaging tool availability
-- The desktop shell is Electron.
-- Core storage, exports, and archive handling are local-only.
-- Sample exports and package artifacts are written by the offline build scripts.
+| Tool | Status |
+|---|---|
+${toolRows}
+
+Fallback policy: when a packaging tool is missing the build still produces
+the runnable app (portable tarball with launcher) plus whatever package
+formats the available tools allow. Windows artifacts are produced by
+\`npm run package:windows\` (electron-builder, portable .exe); .msi/.rpm/
+AppImage require the tools listed above and are skipped on this host.
+
+## Offline guarantee
+
+- The shipped app opens no sockets: no telemetry, update checks, license
+ checks, cloud sync, or remote AI. See SECURITY.md.
+- All exporters (PNG/GIF/PDF/DOCX/PPTX/ZIP) are implemented in-repo with
+ Node built-ins; Electron is the only third-party dependency
+ (dev-time fetch recorded in build/agent_audit.md).
+
+## Verification
+
+- \`bash tests/run_test.sh\` runs the workflow suites (node --test), a
+ startup smoke test of the Electron launcher, the sample-artifact
+ pipeline, and this release build.
`;
fs.writeFileSync(reportFile, report);