Scaffold StepForge: docs, license, audit, npm project
- Environment audit and stack decision in build/agent_audit.md (Node + Electron shell over dependency-free core; deviation recorded) - Rewrite README/ARCHITECTURE/CONTRIBUTING for StepForge - Add SECURITY.md threat model, CODE_OF_CONDUCT.md, CHANGELOG.md, MPL-2.0 - Replace template grep checks with structural workflow check Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+115
-7
@@ -1,14 +1,122 @@
|
||||
# Architecture
|
||||
|
||||
This template is organized around three small areas:
|
||||
StepForge is split into a **dependency-free Node.js core** and a thin
|
||||
**Electron desktop shell**. All product logic lives in `core/` and
|
||||
`exporters/` and runs (and is tested) headlessly with plain `node`. The shell
|
||||
in `app/` only provides the window, the canvas UI, screen capture, hotkeys,
|
||||
and the clipboard.
|
||||
|
||||
- Repository guidance in `README.md` and `CONTRIBUTING.md`.
|
||||
- User-facing templates in `.github/`.
|
||||
- Validation and automation in `tests/` and `.gitea/workflows/`.
|
||||
## Repository Layout
|
||||
|
||||
```text
|
||||
app/ Electron shell: main process, preload bridge, renderer UI
|
||||
core/ Dependency-free domain logic (schema, store, archive, search,
|
||||
placeholders, render AST, png/gif/pdf/zip primitives, locks,
|
||||
snapshots, settings)
|
||||
exporters/ One module per output format, all consuming the Render AST
|
||||
scripts/ bootstrap / verify / build / package scripts (sh + ps1)
|
||||
tests/
|
||||
run_test.sh entrypoint — runs every tests/checks/test_*.sh
|
||||
checks/ shell wrappers that invoke the node test suites
|
||||
unit/ node:test workflow suites
|
||||
fixtures/ test images and guides
|
||||
examples/ sample guide + sample exports
|
||||
assets/ app icon and packaged static assets
|
||||
build/ agent_audit.md, build_report.md, artifacts_manifest.json
|
||||
docs/ file-format and data-model documentation
|
||||
vendor/ reserved for vendored deps (reuse only; nothing fetched)
|
||||
```
|
||||
|
||||
## Data Model
|
||||
|
||||
Internal working storage is **folder-based**; sharing/backups use a
|
||||
**single-file zip archive** (`.sfgz`).
|
||||
|
||||
```text
|
||||
<data root>/ (~/.local/share/stepforge, %APPDATA%/stepforge,
|
||||
settings/ or $STEPFORGE_DATA_DIR)
|
||||
app-settings.json
|
||||
placeholders.json global placeholders
|
||||
templates/<format>/<name>.template.json
|
||||
library/
|
||||
folders.json folder tree + guide->folder mapping
|
||||
guides/<guide-id>/
|
||||
guide.json guide metadata (schema below)
|
||||
steps/<step-id>/
|
||||
step.json
|
||||
original.png never mutated after capture
|
||||
working.png crop target; annotations stay vector JSON
|
||||
history/snapshots/*.zip automated + manual backups
|
||||
index/search-index.json inverted full-text index
|
||||
temp/ previews; cleaned on close
|
||||
shared-links/ linked-guide registry
|
||||
```
|
||||
|
||||
- `guide.json` — schemaVersion, guideId, title, descriptionHtml,
|
||||
placeholders, flags (focusedViewDefault, ...), stepsOrder, favorite,
|
||||
linkedSource, exportProfiles, createdAt/updatedAt.
|
||||
- `step.json` — stepId, parentStepId, kind (`image | empty | content`),
|
||||
status (`todo | in-progress | done`), title, descriptionHtml, hidden,
|
||||
skipped, focusedView {enabled, zoom, panX, panY}, image paths + size,
|
||||
`annotations[]` (normalized scene graph, coordinates in 0..1 fractions of
|
||||
the image), textBlocks[], codeBlocks[], tableBlocks[], links[].
|
||||
|
||||
All writes are **atomic** (write to `*.tmp`, fsync, rename). Deleting a guide
|
||||
moves it to `library/trash/` first.
|
||||
|
||||
## Annotation Scene Graph
|
||||
|
||||
Annotations are stored as normalized JSON, never as an editor-library blob.
|
||||
Coordinates are fractions of the image (resolution-independent). Types:
|
||||
`rect, oval, line, arrow, text, tooltip, number, blur, highlight, magnify,
|
||||
cursor`. The same geometry is rendered by the editor canvas (HTML5 canvas)
|
||||
and by the export rasterizer (`core/raster.js`), so what you see is what
|
||||
exports.
|
||||
|
||||
## Render Pipeline
|
||||
|
||||
```text
|
||||
guide.json + step.json + settings
|
||||
│ core/renderast.js (placeholder expansion, numbering, filtering
|
||||
▼ hidden/skipped, focused-view geometry)
|
||||
Render AST ──► exporters/json.js .json + steps-<title>/ images
|
||||
──► exporters/markdown.js .md + steps-<title>/ images
|
||||
──► exporters/html-simple.js single self-contained .html
|
||||
──► exporters/html-rich.js checkboxes + floating TOC
|
||||
──► exporters/pdf.js native PDF writer (core/pdf.js)
|
||||
──► exporters/gif.js GIF89a encoder (core/gif.js)
|
||||
──► exporters/image-bundle.js annotated PNGs + metadata
|
||||
──► exporters/docx.js zip+XML (core/zip.js)
|
||||
──► exporters/pptx.js zip+XML (core/zip.js)
|
||||
```
|
||||
|
||||
Image-bearing exporters rasterize annotations with `core/raster.js` on top of
|
||||
PNG pixels decoded by `core/png.js`. Every exporter accepts a template object
|
||||
(per-format settings persisted under `settings/templates/`, shareable as
|
||||
`.sfglt` zip files).
|
||||
|
||||
## Shell / Core Boundary
|
||||
|
||||
The renderer never touches the filesystem. `app/preload.js` exposes a typed
|
||||
IPC API (`stepforge.*`), and `app/main.js` routes calls into `core/`. Screen
|
||||
capture uses Electron's `desktopCapturer` (full screen, window) and an
|
||||
overlay window for region selection; hotkeys use `globalShortcut`.
|
||||
|
||||
## Security Rules
|
||||
|
||||
- Zero network code paths: no sockets, no telemetry, no update or license
|
||||
checks, no remote fonts in exports.
|
||||
- Archive imports validate every entry name against path traversal and
|
||||
absolute paths before extraction (`core/zip.js`).
|
||||
- Linked guides use sidecar `*.lock-sfgz` lock files; conflicts surface a
|
||||
keep-editing / discard dialog and last-write-wins is documented.
|
||||
- Renderer runs with `contextIsolation: true`, `nodeIntegration: false`,
|
||||
and `sandbox` enabled; only the preload API is exposed.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Update the documentation and templates.
|
||||
2. Put shell checks in `tests/checks/`.
|
||||
1. Change core/exporter logic together with its workflow tests in
|
||||
`tests/unit/`.
|
||||
2. Put shell checks in `tests/checks/` so the shared runner picks them up.
|
||||
3. Run `bash tests/run_test.sh` locally.
|
||||
4. Open a pull request so Gitea Actions can verify the template on PR open.
|
||||
4. Open a pull request so CI can verify on PR open.
|
||||
|
||||
Reference in New Issue
Block a user