multimodel-dev-os 3.1.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ai/policies/registry-policy.yaml +29 -1
- package/.ai/registries/trusted-keys.yaml +12 -0
- package/.ai/schema/registry-manifest.schema.json +31 -2
- package/.ai/schema/registry-policy.schema.json +37 -1
- package/.ai/schema/trusted-keys.schema.json +69 -0
- package/AGENTS.md +22 -26
- package/MEMORY.md +34 -11
- package/README.md +2 -1
- package/RUNBOOK.md +28 -36
- package/TASKS.md +15 -5
- package/bin/multimodel-dev-os.js +1366 -548
- package/docs/.vitepress/config.js +3 -1
- package/docs/architecture.md +3 -1
- package/docs/index.md +5 -5
- package/docs/npm-publishing.md +5 -5
- package/docs/package-safety.md +17 -0
- package/docs/public/llms-full.txt +5 -1
- package/docs/public/llms.txt +6 -1
- package/docs/public/sitemap.xml +15 -0
- package/docs/registry-policy.md +29 -1
- package/docs/registry-security.md +73 -6
- package/docs/registry-signing.md +70 -0
- package/docs/registry-sync.md +5 -2
- package/docs/registry-trust-store.md +66 -0
- package/docs/release-policy.md +6 -5
- package/docs/security-threat-model.md +96 -0
- package/docs/testing.md +25 -2
- package/docs/trusted-registries.md +1 -1
- package/docs/v3-roadmap.md +17 -6
- package/docs/v3.5.0-readiness.md +46 -0
- package/package.json +5 -2
- package/scripts/build-cli.js +45 -3
- package/scripts/check-build-fresh.js +52 -0
- package/scripts/install.ps1 +1 -1
- package/scripts/install.sh +1 -1
- package/scripts/verify.js +327 -14
- package/scripts/verify.sh +10 -0
- package/src/catalog/loader.js +117 -0
- package/src/cli/args.js +118 -0
- package/src/cli/help.js +60 -0
- package/src/cli/main.js +6263 -0
- package/src/core/globals.js +52 -0
- package/src/core/hashes.js +15 -0
- package/src/core/policy.js +44 -0
- package/src/core/security.js +61 -0
- package/src/core/yaml.js +136 -0
- package/src/plugin/manifest.js +95 -0
- package/src/registry/provenance.js +114 -0
- package/src/registry/signing.js +392 -0
- package/src/registry/sources.js +40 -0
- package/src/registry/trust-store.js +41 -0
- package/src/registry/validation.js +45 -0
- package/src/registry/verdict.js +51 -0
- package/tests/README.md +37 -0
- package/tests/fixtures/README.md +22 -0
- package/tests/fixtures/custom-template-example/README.md +10 -0
- package/tests/fixtures/proposals/approved-append-line.md +28 -0
- package/tests/fixtures/proposals/approved-create-file.md +29 -0
- package/tests/fixtures/proposals/approved-replace-text.md +30 -0
- package/tests/fixtures/proposals/existing-create-file-no-overwrite.md +29 -0
- package/tests/fixtures/proposals/no-operations.md +18 -0
- package/tests/fixtures/proposals/path-traversal.md +29 -0
- package/tests/fixtures/proposals/pending-proposal.md +29 -0
- package/tests/fixtures/proposals/protected-path.md +29 -0
- package/tests/fixtures/proposals/replace-multiple-without-allow.md +30 -0
- package/tests/fixtures/registry-overrides/README.md +20 -0
- package/tests/fixtures/signed-registries/README.md +4 -0
- package/tests/fixtures/signed-registries/revoked-key/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/revoked-key/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/revoked-key/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/tampered-manifest/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/tampered-manifest/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/tampered-manifest/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/trusted-keys.yaml +23 -0
- package/tests/fixtures/signed-registries/unsigned-remote-required/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/unsigned-remote-required/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/unsigned-remote-required/registry-manifest.yaml +9 -0
- package/tests/fixtures/signed-registries/unsupported-algorithm/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/unsupported-algorithm/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/unsupported-algorithm/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/valid-signed-registry/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/valid-signed-registry/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/valid-signed-registry/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/wrong-key/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/wrong-key/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/wrong-key/registry-manifest.yaml +14 -0
- package/tests/smoke/README.md +37 -0
- package/tests/smoke/cli-smoke.md +49 -0
- package/tests/unit/build-output.test.js +40 -0
- package/tests/unit/catalog-loader.test.js +44 -0
- package/tests/unit/path-safety.test.js +62 -0
- package/tests/unit/plugin-manifest.test.js +94 -0
- package/tests/unit/prepublish-guard.test.js +35 -0
- package/tests/unit/registry-e2e-signature-fixtures.test.js +288 -0
- package/tests/unit/registry-policy.test.js +52 -0
- package/tests/unit/registry-provenance.test.js +185 -0
- package/tests/unit/registry-public-signing.test.js +109 -0
- package/tests/unit/registry-signature-policy.test.js +100 -0
- package/tests/unit/registry-signing.test.js +193 -0
- package/tests/unit/registry-trust-store.test.js +133 -0
- package/tests/unit/registry-url-validation.test.js +64 -0
- package/tests/unit/yaml.test.js +92 -0
package/docs/testing.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# MultiModel Dev OS — Testing Guide (v3.
|
|
1
|
+
# MultiModel Dev OS — Testing Guide (v3.5.0+)
|
|
2
2
|
|
|
3
3
|
This document outlines the testing strategy, tools, and execution processes for MultiModel Dev OS.
|
|
4
4
|
|
|
@@ -64,6 +64,19 @@ npm test
|
|
|
64
64
|
- Asserts that publishing blocks without `MMDO_ALLOW_PUBLISH=true`.
|
|
65
65
|
- Permits stable major versions >= 2.
|
|
66
66
|
|
|
67
|
+
7. **Registry Public-Key Signing (`tests/unit/registry-public-signing.test.js`)**
|
|
68
|
+
- Ed25519 keypair generation and format verification.
|
|
69
|
+
- Public-key signature creation, encoding, and verification checks.
|
|
70
|
+
- Canonical payload generation determinism and nested object sorting.
|
|
71
|
+
|
|
72
|
+
8. **Registry Trust Store (`tests/unit/registry-trust-store.test.js`)**
|
|
73
|
+
- Loading trusted publisher key records from YAML.
|
|
74
|
+
- Strict verification of publisher active status, algorithm, and allowed scopes.
|
|
75
|
+
|
|
76
|
+
9. **Registry Signature Policy (`tests/unit/registry-signature-policy.test.js`)**
|
|
77
|
+
- Enforcement of unsigned registry permissions (local, bundled, remote).
|
|
78
|
+
- Enforcing allowed signature algorithms and trusted publisher requirements.
|
|
79
|
+
|
|
67
80
|
---
|
|
68
81
|
|
|
69
82
|
## 3. Tier 2: Release Verification Audit
|
|
@@ -114,10 +127,20 @@ To ensure the npm package functions flawlessly after installation, we run a loca
|
|
|
114
127
|
```
|
|
115
128
|
3. **Install the generated tarball locally**:
|
|
116
129
|
```bash
|
|
117
|
-
npm install F:\multimodel-dev-os\multimodel-dev-os-3.
|
|
130
|
+
npm install F:\multimodel-dev-os\multimodel-dev-os-3.5.0.tgz --no-audit --no-fund
|
|
118
131
|
```
|
|
119
132
|
4. **Validate npx invocation**:
|
|
120
133
|
```bash
|
|
121
134
|
npx multimodel-dev-os --help
|
|
122
135
|
npx multimodel-dev-os doctor
|
|
123
136
|
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 6. Maintainer Guidelines
|
|
141
|
+
|
|
142
|
+
For contributors and maintainers modifying the codebase:
|
|
143
|
+
1. **Always edit source modules** located under `src/`. Do NOT make manual edits to `bin/multimodel-dev-os.js` directly, as it will be overwritten during compilation.
|
|
144
|
+
2. **Execute the build script** via `npm run build` after completing modifications to compile the single-file binary.
|
|
145
|
+
3. **Execute Vitest unit tests** (`npm test`) to ensure all core modules pass verification gates in isolation.
|
|
146
|
+
4. **Execute release verification** (`npm run verify`) to run the strict verification pipeline (250+ assertions check compiled binary, folder layouts, sitemaps, etc.).
|
|
@@ -56,7 +56,7 @@ To guarantee that remote catalogs have not been tampered with in transit, the re
|
|
|
56
56
|
1. **Manifest File (`manifest.json`):** Every verified remote registry publishes a manifest file containing a map of all relative files in the catalog and their expected SHA256 checksums.
|
|
57
57
|
2. **SHA256 Verification:** During `registry sync`, the client downloads the manifest and computes the SHA256 hash of all retrieved assets.
|
|
58
58
|
3. **Local Audit:** The computed hashes are written to `checksums.json` in the cache directory.
|
|
59
|
-
4. **Signature Verification (v3.
|
|
59
|
+
4. **Signature Verification (v3.5.0-prep)**: The `signature` object or `signatures` array in the manifest is cryptographically verified using Ed25519 public-key signature verification against keys registered in the trust store (`.ai/registries/trusted-keys.yaml`).
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
package/docs/v3-roadmap.md
CHANGED
|
@@ -7,12 +7,25 @@ This document outlines the development path, completed milestones, and future pl
|
|
|
7
7
|
## 1. Current Status
|
|
8
8
|
|
|
9
9
|
> [!IMPORTANT]
|
|
10
|
-
> **v3.
|
|
10
|
+
> **v3.5.0 is the active stable release** on the public npm registry. All features below marked ✅ are shipped and production-ready.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## 2. Completed Milestones
|
|
15
15
|
|
|
16
|
+
### v3.5.0 — Trusted Registry Signing + Provenance ✅
|
|
17
|
+
- **Asymmetric Ed25519 Signatures**: Cryptographic verification of remote registry manifests using publisher public keys to secure remote sync.
|
|
18
|
+
- **Trusted Key Store**: Manages active public keys, publishers, and scopes via `.ai/registries/trusted-keys.yaml` configuration.
|
|
19
|
+
- **Registry Provenance Lockfile**: Keeps a committed `.ai/registry-lock.json` containing synced hashes, timestamps, and verdicts to detect local cache tampering.
|
|
20
|
+
- **Structured Verdicts**: Deployed `createTrustVerdict` to generate uniform verification reporting for CLI audits, lockfiles, and diagnostics.
|
|
21
|
+
- **Signed Registry E2E Fixtures**: Comprehensive offline test suite validating valid, tampered, wrong key, revoked key, unsigned, and unsupported algorithm states.
|
|
22
|
+
|
|
23
|
+
### v3.2.0 — Stable Modular Build + Package Governance ✅
|
|
24
|
+
- **Build Freshness Auditing**: Integrated `check-build-fresh.js` to ensure the generated single-file CLI binary matches standard ES modules under `src/` dynamically.
|
|
25
|
+
- **Hardened Package Governance**: Configured the NPM manifest (`package.json`) to include the modular source folder (`src/`) and unit test suites (`tests/unit/`) for developer auditability, while verifying the strict exclusion of sensitive and temporary files.
|
|
26
|
+
- **Cross-Platform CI Pipeline**: Configured a complete multi-platform CI verification matrix on GitHub Actions covering Windows, Linux, and macOS across Node.js versions `20.x` and `22.x`.
|
|
27
|
+
- **Harden Build & Verification Gates**: Applied post-build validations asserting shebang count uniqueness, warning headers, and URL shell-injection safety, while expanding integration audits to 269 assertions.
|
|
28
|
+
|
|
16
29
|
### v3.1.0 — Modular Source Layout + Formal Unit Tests ✅
|
|
17
30
|
- **Modular Source Layout**: Refactored the monolithic CLI structure into isolated, clean modules under `src/` (core, registry, catalog, plugin, cli).
|
|
18
31
|
- **Programmatic Compiler**: Programmed `scripts/build-cli.js` using `esbuild` to compile modules into a single zero-dependency executable (`bin/multimodel-dev-os.js`) with shebang preservation.
|
|
@@ -74,11 +87,9 @@ All releases follow this strict publishing checklist:
|
|
|
74
87
|
|
|
75
88
|
---
|
|
76
89
|
|
|
77
|
-
## 4.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
* **Decentralized Trust Anchors**: Trust anchors configuration allowing teams to pin public keys of verified catalog authors.
|
|
81
|
-
* **Tamper-Proof Audit Chain**: Signed change logs and history verification.
|
|
90
|
+
## 4. In Progress: v3.6.0-prep / Sprint 4 — Remote Key Sync & GPG Signatures
|
|
91
|
+
- **Remote Key Sync**: Enable syncing public keys directly from approved remote registries.
|
|
92
|
+
- **GPG Compatibility**: Support GPG signatures for enterprise-controlled repositories.
|
|
82
93
|
|
|
83
94
|
---
|
|
84
95
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# v3.5.0 Release Readiness Checklist
|
|
2
|
+
|
|
3
|
+
This document tracks the release readiness checklist for MultiModel Dev OS v3.5.0.
|
|
4
|
+
The v3.5.0 milestone represents the integration of HMAC-SHA256 provenance lockfiles, Ed25519 public-key signature checks, and the trusted publisher key store.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Release Governance Status
|
|
9
|
+
|
|
10
|
+
> [!WARNING]
|
|
11
|
+
> **Status:** `Pending (Internal Preparation)`
|
|
12
|
+
> This is an unreleased internal development build. Do not tag, publish to npm, or mark v3.5.0 as released.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Readiness Checklist
|
|
17
|
+
|
|
18
|
+
### 1. Cryptography and Identity Trust
|
|
19
|
+
- [x] **Ed25519 Public-Key Signatures**: Asymmetric signing and timing-safe verification verified end-to-end using Node.js built-ins.
|
|
20
|
+
- [x] **Zero Runtime Dependencies**: Cryptographic functions use native Node `crypto` only.
|
|
21
|
+
- [x] **Trust Store**: Key loading and parsing validated with active status, expiration, and scope constraint checks.
|
|
22
|
+
- [x] **Deterministic Serialization**: Canonical payload sorting proven stable and deterministic across platforms.
|
|
23
|
+
|
|
24
|
+
### 2. End-to-End Fixtures
|
|
25
|
+
- [x] **Valid Signed Registry**: Proven to pass verification.
|
|
26
|
+
- [x] **Tampered Manifest**: Rejected during verification with signature verification errors.
|
|
27
|
+
- [x] **Wrong Signing Key**: Rejected as untrusted.
|
|
28
|
+
- [x] **Revoked/Disabled Keys**: Correctly blocked by trust store status gates.
|
|
29
|
+
- [x] **Unsupported Algorithms**: Properly rejected by policy validation.
|
|
30
|
+
- [x] **Lockfile & Provenance Integrity**: Local `registry-lock.json` entries record precise verdicts and error details.
|
|
31
|
+
|
|
32
|
+
### 3. Build & Package Hygiene
|
|
33
|
+
- [x] **Generated CLI Freshness**: `scripts/check-build-fresh.js` validates that `bin/multimodel-dev-os.js` matches the `src/` modules.
|
|
34
|
+
- [x] **Shebang & Header Validations**: Generated binary has exactly one shebang and includes the warning header.
|
|
35
|
+
- [x] **No Private Keys Committed**: No private keys or `.ai/registry-signing-key` files are tracked by Git.
|
|
36
|
+
- [x] **Clean Packing Exclusion**: Manifest configuration filters out `.npmrc`, `.env`, private keys, local tarballs, and temporary smoke directories.
|
|
37
|
+
|
|
38
|
+
### 4. Command Safety & UX
|
|
39
|
+
- [x] **URL Safety Gate**: No shell-based URL interpolation is used. Synchronous fetching uses `execFileSync` arguments.
|
|
40
|
+
- [x] **Approval Gated Sync**: `registry sync` strictly requires `--approved` flag before performing network fetches.
|
|
41
|
+
- [x] **Offline Stability**: Registry verification and catalog features operate offline using cache directory fixtures.
|
|
42
|
+
|
|
43
|
+
### 5. Verification Metrics
|
|
44
|
+
- [x] **Unit Test Suite**: All unit tests pass cleanly.
|
|
45
|
+
- [x] **Strict Verification Assertions**: `scripts/verify.js` executes successfully with zero failures.
|
|
46
|
+
- [x] **Documentation Coverage**: Threat models, architecture guides, policies, and roadmap files are updated.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multimodel-dev-os",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"bin": {
|
|
5
5
|
"multimodel-dev-os": "bin/multimodel-dev-os.js"
|
|
6
6
|
},
|
|
@@ -35,12 +35,15 @@
|
|
|
35
35
|
"!docs/.vitepress/cache/",
|
|
36
36
|
"examples/",
|
|
37
37
|
"bin/",
|
|
38
|
+
"src/",
|
|
39
|
+
"tests/",
|
|
38
40
|
"assets/"
|
|
39
41
|
],
|
|
40
42
|
"scripts": {
|
|
41
43
|
"build": "node scripts/build-cli.js",
|
|
44
|
+
"check:build": "node scripts/check-build-fresh.js",
|
|
42
45
|
"test": "vitest run",
|
|
43
|
-
"verify": "npm run build && npm test && node scripts/verify.js",
|
|
46
|
+
"verify": "npm run check:build && npm test && node scripts/verify.js",
|
|
44
47
|
"verify:bash": "bash scripts/verify.sh",
|
|
45
48
|
"test:cli": "node bin/multimodel-dev-os.js verify",
|
|
46
49
|
"pack:template": "bash scripts/pack-template.sh",
|
package/scripts/build-cli.js
CHANGED
|
@@ -1,16 +1,58 @@
|
|
|
1
1
|
import esbuild from 'esbuild';
|
|
2
|
+
import { existsSync, chmodSync, readFileSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
const entryPoint = 'src/cli/main.js';
|
|
5
|
+
const outfile = 'bin/multimodel-dev-os.js';
|
|
6
|
+
|
|
7
|
+
if (!existsSync(entryPoint)) {
|
|
8
|
+
console.error(`[ERROR] Entrypoint file not found: ${entryPoint}`);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
2
11
|
|
|
3
12
|
esbuild.build({
|
|
4
|
-
entryPoints: [
|
|
13
|
+
entryPoints: [entryPoint],
|
|
5
14
|
bundle: true,
|
|
6
15
|
platform: 'node',
|
|
7
16
|
format: 'esm',
|
|
8
|
-
outfile:
|
|
17
|
+
outfile: outfile,
|
|
9
18
|
banner: {
|
|
10
19
|
js: `#!/usr/bin/env node\n// Generated from src/. Do not edit directly.\n`
|
|
11
20
|
}
|
|
12
21
|
}).then(() => {
|
|
13
|
-
|
|
22
|
+
// Post-build validation & hardening
|
|
23
|
+
try {
|
|
24
|
+
const content = readFileSync(outfile, 'utf8');
|
|
25
|
+
|
|
26
|
+
// 1. Check shebang counts
|
|
27
|
+
const shebangMatches = content.match(/^#!/g) || [];
|
|
28
|
+
const totalShebangs = (content.match(/#!/g) || []).length;
|
|
29
|
+
|
|
30
|
+
// We expect exactly one shebang at the very top
|
|
31
|
+
if (totalShebangs !== 1 || !content.startsWith('#!/usr/bin/env node')) {
|
|
32
|
+
console.error('[ERROR] Compiled output has invalid shebang configuration.');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 2. Check warning header
|
|
37
|
+
if (!content.includes('// Generated from src/. Do not edit directly.')) {
|
|
38
|
+
console.error('[ERROR] Compiled output is missing the generation warning header.');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 3. Check for unsafe URL interpolation patterns
|
|
43
|
+
if (content.includes("mod.get('${targetUrl}'") || (content.includes('execSync(`node -e "') && content.includes('${targetUrl}'))) {
|
|
44
|
+
console.error('[ERROR] Compiled output contains unsafe registry URL interpolation!');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 4. Set execution permissions (0755)
|
|
49
|
+
chmodSync(outfile, 0o755);
|
|
50
|
+
|
|
51
|
+
console.log('Build succeeded.');
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.error('Post-build verification failed:', e.message);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
14
56
|
}).catch((err) => {
|
|
15
57
|
console.error('Build failed:', err);
|
|
16
58
|
process.exit(1);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import esbuild from 'esbuild';
|
|
2
|
+
import { readFileSync, unlinkSync, existsSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
const entryPoint = 'src/cli/main.js';
|
|
5
|
+
const currentFile = 'bin/multimodel-dev-os.js';
|
|
6
|
+
const tempFile = 'bin/multimodel-dev-os.tmp.js';
|
|
7
|
+
|
|
8
|
+
if (!existsSync(entryPoint)) {
|
|
9
|
+
console.error(`[ERROR] Entrypoint file not found: ${entryPoint}`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!existsSync(currentFile)) {
|
|
14
|
+
console.error(`[ERROR] Current build file not found: ${currentFile}`);
|
|
15
|
+
console.error('Generated CLI is stale. Run npm run build and commit bin/multimodel-dev-os.js.');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await esbuild.build({
|
|
21
|
+
entryPoints: [entryPoint],
|
|
22
|
+
bundle: true,
|
|
23
|
+
platform: 'node',
|
|
24
|
+
format: 'esm',
|
|
25
|
+
outfile: tempFile,
|
|
26
|
+
banner: {
|
|
27
|
+
js: `#!/usr/bin/env node\n// Generated from src/. Do not edit directly.\n`
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const currentContent = readFileSync(currentFile, 'utf8');
|
|
32
|
+
const tempContent = readFileSync(tempFile, 'utf8');
|
|
33
|
+
|
|
34
|
+
// Clean up temp file immediately
|
|
35
|
+
unlinkSync(tempFile);
|
|
36
|
+
|
|
37
|
+
const normalize = str => str.replace(/\r\n/g, '\n');
|
|
38
|
+
|
|
39
|
+
if (normalize(currentContent) !== normalize(tempContent)) {
|
|
40
|
+
console.error('[ERROR] Generated CLI is stale. Run npm run build and commit bin/multimodel-dev-os.js.');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('Generated CLI is fresh.');
|
|
45
|
+
process.exit(0);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error('Build freshness check failed:', err);
|
|
48
|
+
if (existsSync(tempFile)) {
|
|
49
|
+
unlinkSync(tempFile);
|
|
50
|
+
}
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
package/scripts/install.ps1
CHANGED
package/scripts/install.sh
CHANGED