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
90 changes: 89 additions & 1 deletion .github/workflows/forgecore-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches: ["**"]
pull_request:

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
build-portable:
runs-on: ubuntu-latest
Expand All @@ -15,7 +18,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
node-version: "22.12.0"
cache: "npm"

- name: Install dependencies
Expand Down Expand Up @@ -89,3 +92,88 @@ jobs:
dist/specs-manifest.signatures.json
dist/specs-manifest.sig.stub.json
dist/release-feed-alignment.json

e2e-tests:
runs-on: windows-latest
timeout-minutes: 20

steps:
- uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "22.12.0"
cache: "npm"
cache-dependency-path: |
package-lock.json
NeuralOS_Master_Build/package-lock.json

- name: Install root dependencies
run: npm ci

- name: Install NeuralOS dependencies
working-directory: NeuralOS_Master_Build
run: npm ci
env:
HUSKY: "0"

- name: Install renderer asset dependencies
working-directory: NeuralOS_Master_Build
run: |
npm --prefix packages/modules/xxxplorer ci
npm --prefix packages/shells/winshadow ci
env:
HUSKY: "0"

- name: Build renderer assets
working-directory: NeuralOS_Master_Build
run: npm run build:assets

- name: Rebuild native modules for Electron
working-directory: NeuralOS_Master_Build
run: npm run rebuild
env:
HUSKY: "0"

- name: Run Playwright E2E tests
working-directory: NeuralOS_Master_Build
run: npm run test:e2e:ci
env:
CI: true
NODE_ENV: test
ELECTRON_ENABLE_LOGGING: true
ELECTRON_ENABLE_STACK_DUMPING: true

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: |
NeuralOS_Master_Build/playwright-report/
NeuralOS_Master_Build/test-results/
retention-days: 14

lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "22.12.0"
cache: "npm"
cache-dependency-path: NeuralOS_Master_Build/package-lock.json

- name: Install NeuralOS dependencies
working-directory: NeuralOS_Master_Build
run: npm ci
env:
HUSKY: "0"

- name: Run ESLint
working-directory: NeuralOS_Master_Build
run: npx eslint .
83 changes: 83 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Release workflow uses Node 20 while CI tests with Node 22.12.0

The CI workflow (forgecore-ci.yml:18) consistently uses node-version: "22.12.0" for all three jobs, but the new release workflow (release.yml:21) uses node-version: "20". The release workflow runs the same scripts (build:portable, verify:portable, verify:release, release_portable.cjs) that CI tests with Node 22. If any of these scripts use Node 22-specific APIs or behavior, the release build will fail even though CI passes. The release pipeline should use the same Node version that CI validates against.

Suggested change
node-version: "20"
node-version: "22.12.0"
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

cache: "npm"

- name: Install dependencies
run: npm ci

- name: Generate CI architect key
run: |
node -e "
const crypto = require('crypto');
const fs = require('fs');
const pair = crypto.generateKeyPairSync('ed25519');
const pem = pair.privateKey.export({ type: 'pkcs8', format: 'pem' });
fs.writeFileSync('core/architect.key', pem, { encoding: 'utf8' });
console.log('[CI] architect.key generated for release signing');
"

- name: Install Wine for cross-platform build
run: |
sudo dpkg --add-architecture i386
sudo apt-get update -qq
sudo apt-get install -y -qq wine64 > /dev/null 2>&1

- name: Refresh manifest and build portable
run: npm run build:portable

- name: Generate release manifest
run: node scripts/release_portable.cjs

- name: Verify artifact
run: npm run verify:portable

- name: Verify release hash chain
run: npm run verify:release

- name: Identify build artifact
id: artifact
run: |
EXE=$(ls dist/*.exe 2>/dev/null | head -1)
if [ -z "$EXE" ]; then
echo "No .exe found in dist/"
exit 1
fi
echo "path=$EXE" >> "$GITHUB_OUTPUT"
echo "name=$(basename $EXE)" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Unquoted $EXE in basename produces wrong artifact name due to space in filename

The artifact name pattern in package.json:116 is forgecore-os ${version}.exe, which resolves to e.g. forgecore-os 2.0.0.exe (containing a space). On line 65, basename $EXE is called without quoting $EXE. Shell word-splitting will split dist/forgecore-os 2.0.0.exe into two arguments: dist/forgecore-os and 2.0.0.exe. basename interprets two arguments as basename NAME SUFFIX, so it returns forgecore-os (ignoring the second arg since it's not a matching suffix) instead of the full forgecore-os 2.0.0.exe. This causes the release body to display an incorrect artifact name.

Suggested change
echo "name=$(basename $EXE)" >> "$GITHUB_OUTPUT"
echo "name=$(basename "$EXE")" >> "$GITHUB_OUTPUT"
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

SHA=$(sha256sum "$EXE" | cut -d' ' -f1)
echo "sha256=$SHA" >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
${{ steps.artifact.outputs.path }}
dist/release-manifest.json
dist/*.sha256.txt
body: |
## ForgeCore OS ${{ github.ref_name }}

**Artifact:** `${{ steps.artifact.outputs.name }}`
**SHA-256:** `${{ steps.artifact.outputs.sha256 }}`

See `release-manifest.json` for full integrity chain.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ memory/
NeuralOS_Master_Build/memory/
NeuralOS_Master_Build/proof_bundle/OPERATIONS.log
test-results/
NeuralOS_Master_Build/playwright-report/

# Local-only workflow/hook artifacts
.github/workflows/build.yml
.github/workflows/verify-all.yml
NeuralOS_Master_Build/.husky/
NeuralOS_Master_Build/packages/sample.txt

# IDE / editor
.idea/
Expand Down
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
9 changes: 9 additions & 0 deletions NeuralOS_Master_Build/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"singleQuote": true,
"trailingComma": "none",
"tabWidth": 4,
"semi": true,
"printWidth": 120,
"arrowParens": "always",
"endOfLine": "lf"
}
42 changes: 42 additions & 0 deletions NeuralOS_Master_Build/NEXT_TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Next Todo List - Phase 2

Updated: 2026-05-08

Previous cycle completed: repo hygiene, CI command alignment, docs, release notes, full E2E, lint, asset build, Windows packaging fallback, and packaged smoke test.

## Priority 1 - Commit And PR Readiness

- [x] Review the current diff from the repository root at `C:/Users/KickA`.
- [x] Stage the intended files only: `.gitignore`, `.github/workflows/forgecore-ci.yml`, root `README.md`, `NeuralOS_Master_Build/README.md`, `NeuralOS_Master_Build/NEXT_TODO.md`, `NeuralOS_Master_Build/docs/RELEASE_NOTES.md`, packaged QA evidence, `NeuralOS_Master_Build/modules/window.js`, and the removal of `NeuralOS_Master_Build/test-results/.last-run.json` from tracking.
- [x] Confirm ignored local artifacts stay out of Git status: stale workflow drafts, subproject `.husky/`, `packages/sample.txt`, Playwright report output, and packaged build output.
- [x] Commit the change set on `codex/next-15-ci-hooks`. Outcome: committed as `ci: harden neuralos verification workflow`.
- [x] Push the branch and open or update the PR with test results. Outcome: pushed branch and updated PR #7.

## Priority 2 - Native Build Environment

- [x] Install Visual Studio C++ Build Tools with MSVC, Windows SDK, and Desktop C++ workload.
- [x] Rerun `npm run rebuild` and confirm `node-pty` rebuilds without the fallback.
- [x] Rerun default `npm run build:win` and confirm the package builds without `--config.npmRebuild=false`.
- [x] Rerun `npm run test:packaged` against the default build artifact.
- [x] Decide whether to add a `postinstall` script for `electron-builder install-app-deps`. Outcome: leave it out for now to keep `npm ci` lighter; explicit rebuild/build steps cover native alignment.

## Priority 3 - Repository Boundary Decision

- [x] Decide whether `NeuralOS_Master_Build` should remain a subdirectory of the `C:/Users/KickA` repository. Outcome: keep the current root for this branch.
- [x] If keeping the current root, add a short root-level map that explains where NeuralOS work lives.
- [x] If splitting the project, plan a clean repo extraction path that preserves needed history. Outcome: no split now; defer extraction planning until the current CI branch lands.
- [x] Update CI paths and package commands to match the chosen repository boundary. Outcome: current CI paths already match the retained root.

## Priority 4 - Release QA Evidence

- [x] Run the manual QA checklist for WinShadow, NeuralMac, NeuralLinux, XXXplorer, and the system layer.
- [x] Verify shell switching and PTY behavior inside the packaged app, not only the dev app.
- [x] Capture screenshots or notes from the packaged-app QA pass.
- [x] Add the QA evidence summary to `docs/RELEASE_NOTES.md`.
- [x] Confirm the portable EXE launches from a clean temporary directory.

## Follow-Up Watchlist

- [ ] Consider adding a dedicated packaged shell-switch Playwright test so this lifecycle regression is caught before manual QA.
- [ ] Triage XXXplorer visual glitching separately from packaged startup smoke.
- [ ] Decide later whether `NeuralOS_Master_Build` should become its own Git repository after the CI/hooks branch is merged.
108 changes: 108 additions & 0 deletions NeuralOS_Master_Build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
## NeuralOS Master Build

Sovereign Desktop Runtime built on Electron 41. Provides a triple-shell architecture (WinShadow, NeuralMac, NeuralLinux) with hot-swap switching, a hardware-sealed identity system, and capability-based IPC.

### Quick Start

```bash
cd NeuralOS_Master_Build
npm install
npm run rebuild # rebuild node-pty for Electron ABI
npm start # launch in development mode
```

### Architecture

The main process is split into focused modules under `modules/`:

| Module | Purpose |
| ------------- | ------------------------------------------------------------------------- |
| `config.js` | Paths, constants, `DEFAULT_SYSTEM_STATE`, native launch allowlist |
| `context.js` | Shared mutable singleton (`mainWindow`, `ptyProcess`) |
| `state.js` | Deep-merge state engine — load, persist, normalize |
| `hardware.js` | Ed25519 hardware seal generation |
| `logging.js` | Session memory log + proof-of-operation log |
| `pty.js` | Pseudo-terminal lifecycle management |
| `window.js` | BrowserWindow creation, CSP headers, permission handler, shell resolution |
| `ipc.js` | All IPC handlers (system, fs, vpn, pod, shell, state) |

The entry point `main.desktop.js` is a 51-line orchestrator that wires these modules together and manages the app lifecycle.

### Renderer API

`preload.js` exposes `window.neuralos` with eight namespaces via `contextBridge`:

- **shell** — `getMode()`, `switch(mode)`, `execute(cmd)`, `onMemoryUpdate(cb)`
- **core** — `getSeal()`
- **fs** — `ls(dir)`, `verify(path)`, `vaultMove(src, dest)`
- **vpn** — `start(config)`, `stop()`, `status()`
- **pod** — `start()`, `stop()`, `status()`
- **state** — `get()`, `set(patch)`, `onUpdate(cb)`
- **pty** — `send(data)`, `onData(cb)`, `resize(cols, rows)`
- **system** — `audit()`, `launch(appPath)`, `metrics()`

### Security

- `sandbox: true`, `contextIsolation: true`, `nodeIntegration: false`, `webSecurity: true`
- Content-Security-Policy injected via `session.webRequest.onHeadersReceived` — restricts to `self`/`file:` origins
- `setPermissionRequestHandler` denies all permissions except clipboard
- Native launch targets are allowlisted (no shell injection)

### Scripts

| Script | Description |
| ---------------------- | ----------------------------------------- |
| `npm start` | Launch the app in development mode |
| `npm run proof:lint` | Run ESLint with auto-fix |
| `npm run test:e2e` | Run single smoke test (xxxplorer) |
| `npm run test:e2e:all` | Run all 9 spec files (23 tests) |
| `npm run build:win` | Build portable Windows exe |
| `npm run rebuild` | Rebuild node-pty for current Electron ABI |

### Shell Hot-Swap Behavior

Shell mode is persisted through the state engine and resolved by `modules/window.js` before the renderer loads. `window.neuralos.shell.switch(mode)` accepts `winshadow`, `neuralmac`, and `neurallinux`; invalid modes should fail without mutating persisted state. When a shell bundle is missing or fails to load, the expected recovery path is to keep the last valid shell mode and surface the failure through the renderer/devtools rather than silently switching modes.

### Tests

Nine Playwright E2E spec files in `tests/`:

| Spec | Coverage |
| ------------------------------- | --------------------------------------------- |
| `xxxplorer.spec.ts` | Vault move integrity |
| `xxxplorer-preferences.spec.ts` | Theme and root persistence |
| `state-persistence.spec.ts` | State persistence across launches |
| `winshadow-draft.spec.ts` | Command draft persistence |
| `native-launch.spec.ts` | Allowlist enforcement + injection blocking |
| `shell-hotswap.spec.ts` | Shell mode, execute, switch, hot-swap |
| `system-metrics.spec.ts` | RAM/CPU/battery metrics, audit lifecycle |
| `vpn-pod-ipc.spec.ts` | VPN and Pod start/stop/status |
| `memory-engine.spec.ts` | State get/set/deep-merge, event subscriptions |

### Native Modules

Five Rust NAPI addons (`.node` binaries) ship pre-built:

- `packages/core/neuralpod_core/index.node` — Pod lifecycle
- `packages/core/seal_pulse/index.node` — Seal pulse engine
- `packages/core/trustctl/index.node` — Hash verification
- `packages/core/vaultfs/index.node` — Vault filesystem + TPM enclave
- `packages/modules/vipn/rust/index.node` — VPN bridge

These use N-API (stable ABI) and don't require per-Electron-version rebuilds. `node-pty` is the only native dependency that needs `npm run rebuild` after Electron upgrades.

### Native Module Rebuild Troubleshooting

- If Electron starts but PTY features fail, run `npm run rebuild` from `NeuralOS_Master_Build` and restart the app.
- If rebuild fails on Windows, confirm the Visual Studio C++ build tools and Python are available on `PATH`.
- If the failure only appears after an Electron upgrade, delete `node_modules`, reinstall with `npm install`, then run `npm run rebuild`.
- If packaging on a Windows machine without Visual Studio C++ build tools and verified `node-pty` prebuilds already exist, use `npx electron-builder --windows portable --config.npmRebuild=false`, then run `npm run test:packaged`.
- The Rust NAPI addons are pre-built and should not need per-Electron rebuilds; investigate missing `.node` files or packaging paths before rebuilding those crates.

### Manual QA Checklist

- WinShadow: launch with `npm start`, verify command draft persistence, native launch allowlist behavior, and shell switching controls.
- NeuralMac: switch from WinShadow, confirm the desktop renders, state persists, and switching back does not reset the shell mode.
- NeuralLinux: switch from WinShadow or NeuralMac, verify terminal UI load, PTY input/output, and state persistence across restart.
- XXXplorer: verify vault move integrity, root preference persistence, and theme preference persistence.
- System layer: verify `system.audit()`, `system.metrics()`, VPN status transitions, and Pod status transitions.
Loading
Loading