@stackwright-pro/otters 0.0.0-beta-20260417191149

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/README.md ADDED
@@ -0,0 +1,271 @@
1
+ # @stackwright-pro/otters
2
+
3
+ 🦦🦦 **Pro Otter Ecosystem** — Enterprise features that emerge when Pro otters join the raft.
4
+
5
+ Pro otters don't replace the OSS raft — they extend it. When a Pro otter joins, the entire ecosystem adapts. Page Otter discovers Dashboard Otter and offers live data. Theme Otter discovers CAC requirements and suggests secure variants. The raft self-organizes.
6
+
7
+ ---
8
+
9
+ ## Dynamic Discovery
10
+
11
+ All Pro otters use `list_agents()` for dynamic discovery at startup. This pattern ensures:
12
+
13
+ - **Automatic coordination** — Pro otters find each other and OSS counterparts
14
+ - **Graceful degradation** — Fall back to MCP tools if an otter is missing
15
+ - **Context-aware behavior** — Adapt based on available teammates
16
+
17
+ ```typescript
18
+ // Every Pro otter discovers at startup
19
+ const agents = await list_agents();
20
+ const proOtters = agents.filter((a) => a.name.includes('pro-'));
21
+ const ossOtters = agents.filter((a) => a.name.includes('-otter') && !a.name.includes('pro-'));
22
+ ```
23
+
24
+ ### Pro + OSS Integration
25
+
26
+ When Pro otters join an OSS raft, the following capabilities emerge:
27
+
28
+ | OSS Otter | Pro Enhancement | What Emerges |
29
+ | ------------- | --------------- | -------------------------------------- |
30
+ | Brand Otter | Pro Specs | Brand validation against approved APIs |
31
+ | Theme Otter | Pro Auth | CAC-enabled secure themes |
32
+ | Page Otter | Pro Dashboard | Live data page generation |
33
+ | Foreman Otter | Pro Delegation | Enterprise orchestration with fallback |
34
+
35
+ ### How Pro Otters Discover the OSS Raft
36
+
37
+ ```
38
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
39
+ │ DISCOVERY SEQUENCE │
40
+ ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
41
+ │ │
42
+ │ code-puppy -i -a stackwright-pro-foreman-otter │
43
+ │ │
44
+ │ 1. Pro Foreman starts │
45
+ │ │
46
+ │ 2. list_agents() scans for otters: │
47
+ │ ā”œā”€ā–ŗ OSS Foreman detected: stackwright-foreman-otter │
48
+ │ ā”œā”€ā–ŗ Pro specialists detected: │
49
+ │ │ ā”œā”€ā–ŗ stackwright-pro-api-otter │
50
+ │ │ ā”œā”€ā–ŗ stackwright-pro-data-otter │
51
+ │ │ └─► stackwright-pro-dashboard-otter │
52
+ │ └─► OSS raft detected: │
53
+ │ ā”œā”€ā–ŗ stackwright-brand-otter │
54
+ │ ā”œā”€ā–ŗ stackwright-theme-otter │
55
+ │ └─► stackwright-page-otter │
56
+ │ │
57
+ │ 3. Pro Foreman delegates to OSS Foreman: │
58
+ │ "Delegating Brand → Theme → Pages to OSS Foreman" │
59
+ │ │
60
+ │ 4. Pro capabilities available for addition: │
61
+ │ "API dashboards, CAC auth, OIDC ready" │
62
+ │ │
63
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Installation
69
+
70
+ ```bash
71
+ # Install Pro otters
72
+ npm install @stackwright-pro/otters
73
+
74
+ # Or with pnpm
75
+ pnpm add @stackwright-pro/otters
76
+ ```
77
+
78
+ The postinstall script automatically installs Pro otters to `~/.code_puppy/agents/` for code-puppy discovery.
79
+
80
+ ```bash
81
+ # User has OSS otters installed
82
+ code-puppy -i -a stackwright-foreman-otter
83
+ # Found: Brand āœ“, Theme āœ“, Page āœ“
84
+
85
+ # User installs Pro otters
86
+ npm install @stackwright-pro/otters
87
+
88
+ # Now with Pro discovery
89
+ code-puppy -i -a stackwright-foreman-otter
90
+ # Found: Brand āœ“, Theme āœ“, Page āœ“
91
+ # Pro detected: API Otter āœ“, Data Otter āœ“, Dashboard Otter āœ“
92
+ # "Live API dashboards now available - want some?"
93
+ ```
94
+
95
+ The OSS Foreman Otter orchestrates the base pipeline. When Pro otters are present, they extend it silently — offering capabilities without overwhelming users who don't need them.
96
+
97
+ If you need to re-run the installation:
98
+
99
+ ```bash
100
+ node node_modules/@stackwright-pro/otters/scripts/install-agents.js
101
+ ```
102
+
103
+ ---
104
+
105
+ ## The Pro + OSS Raft: What Emerges
106
+
107
+ When Pro otters combine with the OSS raft, these capabilities emerge:
108
+
109
+ | Combined Otters | Emergent Capability |
110
+ | ---------------------------- | --------------------------------------- |
111
+ | Page Otter + Dashboard Otter | "Add live data to this page?" |
112
+ | Theme Otter + Pro Auth | "Enable CAC on this theme?" |
113
+ | Brand Otter + Pro Specs | "Validate brand against approved APIs?" |
114
+ | Foreman + All Pro Otters | Enterprise orchestration |
115
+ | All Otters + Enterprise Mode | Security posture auto-detected |
116
+
117
+ ---
118
+
119
+ ## The Pro Otter Raft
120
+
121
+ | Otter | Role | Output |
122
+ | ------------------------ | -------------------- | ------------------------------------------------------------- |
123
+ | 🦦🦦 **Foreman Otter** | Project coordinator | Orchestrates full-stack builds (delegates to unified Foreman) |
124
+ | šŸ¦¦šŸ“” **API Otter** | OpenAPI discovery | API entity types, endpoints |
125
+ | šŸ¦¦šŸ“Š **Dashboard Otter** | Live data views | Typed API components |
126
+ | šŸ¦¦šŸ”— **Data Otter** | Endpoint integration | ISR config, filters |
127
+
128
+ ---
129
+
130
+ ## Pro vs OSS Integration
131
+
132
+ | Feature | OSS | Pro Integration |
133
+ | ---------------------- | ------------ | ------------------------------ |
134
+ | Brand discovery | āœ… OSS Otter | āœ… Pro can extend |
135
+ | Theme design | āœ… OSS Otter | āœ… Enterprise themes available |
136
+ | Page building | āœ… OSS Otter | āœ… Live data pages emerge |
137
+ | API dashboards | āŒ | āœ… Discovered dynamically |
138
+ | CAC auth | āŒ | āœ… Suggested when available |
139
+ | Static site generation | āœ… | āœ… Extended with ISR |
140
+
141
+ The key insight: **Pro doesn't replace OSS — it amplifies it.** The OSS raft handles static content, SEO, and standard pages. Pro otters discover gaps in the raft and fill them with enterprise capabilities.
142
+
143
+ ---
144
+
145
+ ## How Pro Integrates
146
+
147
+ ### The Discovery Flow
148
+
149
+ ```
150
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
151
+ │ CODE-PUPPY DISCOVERY │
152
+ ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
153
+ │ │
154
+ │ code-puppy -i -a stackwright-foreman-otter │
155
+ │ │
156
+ │ 1. Lists all available agents │
157
+ │ │
158
+ │ 2. Filters for OSS raft: │
159
+ │ ā”œā”€ā–ŗ Brand Otter āœ“ │
160
+ │ ā”œā”€ā–ŗ Theme Otter āœ“ │
161
+ │ ā”œā”€ā–ŗ Page Otter āœ“ │
162
+ │ └─► Foreman Otter āœ“ │
163
+ │ │
164
+ │ 3. Pro Foreman extends OSS Foreman: │
165
+ │ ā”œā”€ā–ŗ Adds API discovery hooks │
166
+ │ ā”œā”€ā–ŗ Adds ISR configuration │
167
+ │ └─► Adds Dashboard Otter coordination │
168
+ │ │
169
+ │ 4. Emergent suggestions: │
170
+ │ "API spec detected → Generate dashboard?" │
171
+ │ │
172
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
173
+ ```
174
+
175
+ ### Invoking Pro Otters
176
+
177
+ ```bash
178
+ # Full-stack API build (via Foreman delegation)
179
+ code-puppy -i -a stackwright-foreman-otter
180
+
181
+ # API entity discovery (Pro otters work alongside OSS)
182
+ code-puppy -i -a stackwright-pro-api-otter
183
+
184
+ # Live dashboard generation (extends Page Otter)
185
+ code-puppy -i -a stackwright-pro-dashboard-otter
186
+
187
+ # ISR configuration (extends Data layer)
188
+ code-puppy -i -a stackwright-pro-data-otter
189
+ ```
190
+
191
+ ---
192
+
193
+ ## The Pro Pipeline
194
+
195
+ When a Pro otter joins an active OSS build:
196
+
197
+ ```
198
+ User Request (with OpenAPI spec)
199
+ │
200
+ ā–¼
201
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
202
+ │ OSS Foreman Otter │ ◄── Base coordinator
203
+ │ (Pro-aware) │
204
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
205
+ │ discovers Pro capabilities
206
+ ā–¼
207
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
208
+ │ Pro API Otter │ ◄── OpenAPI → typed client
209
+ │ (entity discovery) │ (extends OSS build)
210
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
211
+ │ creates src/generated/*
212
+ ā–¼
213
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
214
+ │ Pro Dashboard Otter │ ◄── Live API data views
215
+ │ (emerges with data) │
216
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
217
+ │ creates pages/api/*
218
+ ā–¼
219
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
220
+ │ Pro Data Otter │ ◄── ISR + endpoint config
221
+ │ (configures refresh) │
222
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
223
+ ā–¼
224
+ USER
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Package Structure
230
+
231
+ ```
232
+ @stackwright-pro/otters/
233
+ ā”œā”€ā”€ package.json
234
+ ā”œā”€ā”€ README.md
235
+ ā”œā”€ā”€ MCP_TOOLS.md # MCP tool documentation
236
+ ā”œā”€ā”€ PRO_OTTER_ARCHITECTURE.md # Architecture details
237
+ ā”œā”€ā”€ scripts/
238
+ │ └── install-agents.js # Postinstall script
239
+ ā”œā”€ā”€ stackwright-pro-foreman-otter.json
240
+ ā”œā”€ā”€ stackwright-pro-api-otter.json
241
+ ā”œā”€ā”€ stackwright-pro-dashboard-otter.json
242
+ └── stackwright-pro-data-otter.json
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Dependencies
248
+
249
+ Pro otters require:
250
+
251
+ - **@stackwright-pro/mcp** — MCP server for API tooling
252
+ - **@stackwright/otters** — OSS otters (installed automatically)
253
+
254
+ ---
255
+
256
+ ## Emergent Capabilities
257
+
258
+ When Pro otters join the raft, unexpected capabilities emerge:
259
+
260
+ | Discovery | Emergent Feature |
261
+ | ---------------------------- | --------------------------------------- |
262
+ | Page Otter + Dashboard Otter | "Add live data to this page?" |
263
+ | Theme Otter + Pro Auth | "Enable CAC on this theme?" |
264
+ | Brand Otter + Pro Specs | "Validate brand against approved APIs?" |
265
+ | All otters + Enterprise | Security posture auto-detected |
266
+
267
+ ---
268
+
269
+ ## License
270
+
271
+ MIT
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@stackwright-pro/otters",
3
+ "version": "0.0.0-beta-20260417191149",
4
+ "description": "Stackwright Pro Otter Raft - AI agents for enterprise features (CAC auth, API dashboards, government use cases)",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/Per-Aspera-LLC/stackwright-pro"
9
+ },
10
+ "devDependencies": {
11
+ "vitest": "^4.0.18",
12
+ "zod": "^3.22.4"
13
+ },
14
+ "exports": {
15
+ "./src": "./src",
16
+ "./pro-foreman": "./src/stackwright-pro-foreman-otter.json"
17
+ },
18
+ "files": [
19
+ "scripts",
20
+ "src"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "peerDependencies": {
26
+ "@stackwright-pro/mcp": "0.0.0-beta-20260417191149"
27
+ },
28
+ "scripts": {
29
+ "generate-checksums": "node scripts/generate-checksums.js",
30
+ "verify-checksums": "node scripts/verify-checksums.js",
31
+ "postinstall": "node scripts/install-agents.js",
32
+ "test": "vitest run",
33
+ "test:watch": "vitest",
34
+ "test:coverage": "vitest run --coverage"
35
+ }
36
+ }
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * generate-checksums.js
4
+ * Computes SHA-256 for every *-otter.json in src/ and writes src/checksums.json
5
+ * Run: node scripts/generate-checksums.js
6
+ * Auto-run: npm prepare (before publish), npm pretest (before tests)
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const crypto = require('crypto');
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+
15
+ const scriptDir = __dirname;
16
+ const packageRoot = path.resolve(scriptDir, '..');
17
+ const srcDir = path.join(packageRoot, 'src');
18
+ const outputFile = path.join(srcDir, 'checksums.json');
19
+
20
+ async function generateChecksums() {
21
+ const entries = await fs.promises.readdir(srcDir);
22
+
23
+ const otterFiles = entries
24
+ .filter((f) => f.endsWith('-otter.json'))
25
+ .sort(); // alphabetical — deterministic output, no excuses
26
+
27
+ const files = {};
28
+ for (const filename of otterFiles) {
29
+ const filePath = path.join(srcDir, filename);
30
+ const raw = await fs.promises.readFile(filePath); // raw Buffer → utf-8 bytes, no funny business
31
+ const digest = crypto.createHash('sha256').update(raw).digest('hex');
32
+ files[filename] = digest;
33
+ }
34
+
35
+ const manifest = {
36
+ version: '1.0',
37
+ algorithm: 'sha256',
38
+ generated: new Date().toISOString(),
39
+ files,
40
+ };
41
+
42
+ await fs.promises.writeFile(outputFile, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
43
+
44
+ console.log(`āœ… checksums.json written with ${otterFiles.length} entr${otterFiles.length === 1 ? 'y' : 'ies'}:`);
45
+ for (const [name, hash] of Object.entries(files)) {
46
+ console.log(` ${name}: ${hash}`);
47
+ }
48
+ }
49
+
50
+ generateChecksums().catch((err) => {
51
+ console.error('āŒ generate-checksums failed:', err.message);
52
+ process.exit(1);
53
+ });
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install script for @stackwright-pro/otters
4
+ * Copies Pro agent JSON files to ~/.code_puppy/agents/ for code-puppy discovery
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const os = require('os');
10
+
11
+ const AGENTS_DIR = path.join(os.homedir(), '.code_puppy', 'agents');
12
+
13
+ // Resolve package root relative to this script's location
14
+ const scriptDir = __dirname;
15
+ const packageRoot = path.resolve(scriptDir, '..');
16
+
17
+ // All Pro otters are in the src/ directory
18
+ const srcDir = path.join(packageRoot, 'src');
19
+
20
+ async function installAgents() {
21
+ try {
22
+ // Ensure ~/.code_puppy/agents/ exists
23
+ await fs.promises.mkdir(AGENTS_DIR, { recursive: true });
24
+
25
+ // Copy all JSON files from src/ to ~/.code_puppy/agents/
26
+ const files = await fs.promises.readdir(srcDir);
27
+
28
+ let installedCount = 0;
29
+ for (const file of files) {
30
+ if (file.endsWith('-otter.json')) {
31
+ const srcPath = path.join(srcDir, file);
32
+ const destPath = path.join(AGENTS_DIR, file);
33
+
34
+ await fs.promises.copyFile(srcPath, destPath);
35
+ console.log(`āœ… Installed: ${file}`);
36
+ installedCount++;
37
+ }
38
+ }
39
+
40
+ // Also install checksums manifest (informational — Python coordinator uses hardcoded constants)
41
+ const checksumsSource = path.join(packageRoot, 'src', 'checksums.json');
42
+ const checksumsDest = path.join(AGENTS_DIR, 'otter-checksums.REFERENCE-ONLY.json');
43
+ if (fs.existsSync(checksumsSource)) {
44
+ await fs.promises.copyFile(checksumsSource, checksumsDest);
45
+ console.log('āœ… Installed: otter-checksums.REFERENCE-ONLY.json');
46
+ }
47
+
48
+ if (installedCount > 0) {
49
+ console.log(`Installing otters from: ${srcDir}`);
50
+ console.log(`\n🦦🦦 Pro otters installed to ${AGENTS_DIR}`);
51
+ } else {
52
+ console.log('āš ļø No Pro otter files found to install');
53
+ }
54
+ } catch (error) {
55
+ console.error(`āŒ FATAL: Failed to install Pro otters: ${error.message}`);
56
+ process.exit(1); // Fail the npm install — surface it early
57
+ }
58
+ }
59
+
60
+ installAgents();
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * verify-checksums.js
4
+ * Read-only: verifies that *-otter.json files match the committed checksums.json
5
+ * Does NOT regenerate. For regeneration: node scripts/generate-checksums.js
6
+ *
7
+ * Exit codes:
8
+ * 0 = all checksums match
9
+ * 1 = one or more mismatches detected (tamper detected or file missing)
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ const crypto = require('crypto');
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const packageRoot = path.resolve(__dirname, '..');
19
+ const srcDir = path.join(packageRoot, 'src');
20
+ const checksumsPath = path.join(srcDir, 'checksums.json');
21
+
22
+ // Read checksums manifest
23
+ let manifest;
24
+ try {
25
+ manifest = JSON.parse(fs.readFileSync(checksumsPath, 'utf8'));
26
+ } catch (err) {
27
+ console.error(`āŒ Cannot read checksums.json: ${err.message}`);
28
+ console.error('Run: node scripts/generate-checksums.js');
29
+ process.exit(1);
30
+ }
31
+
32
+ const expected = manifest.files || {};
33
+ let failures = 0;
34
+ let verified = 0;
35
+
36
+ for (const [filename, expectedHash] of Object.entries(expected)) {
37
+ const filePath = path.join(srcDir, filename);
38
+ try {
39
+ const raw = fs.readFileSync(filePath);
40
+ const actual = crypto.createHash('sha256').update(raw).digest('hex');
41
+ if (actual !== expectedHash) {
42
+ console.error(`āŒ MISMATCH: ${filename}`);
43
+ console.error(` Expected: ${expectedHash.substring(0, 16)}...`);
44
+ console.error(` Actual: ${actual.substring(0, 16)}...`);
45
+ failures++;
46
+ } else {
47
+ console.log(`āœ… ${filename}`);
48
+ verified++;
49
+ }
50
+ } catch (err) {
51
+ console.error(`āŒ MISSING: ${filename} — ${err.message}`);
52
+ failures++;
53
+ }
54
+ }
55
+
56
+ if (failures > 0) {
57
+ console.error(`\n🚨 ${failures} checksum failure(s) detected. Run \`npm install @stackwright-pro/otters\` to restore.`);
58
+ process.exit(1);
59
+ } else {
60
+ console.log(`\nāœ… All ${verified} otter checksums verified.`);
61
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "version": "1.0",
3
+ "algorithm": "sha256",
4
+ "generated": "2026-04-16T15:32:31.051Z",
5
+ "files": {
6
+ "stackwright-pro-api-otter.json": "ad0c3694af41000420229edce4108f860eaa58ab321f8618565d03ebce80bcac",
7
+ "stackwright-pro-auth-otter.json": "e8e02ef1389e0d5e55bfa6d960a050ab976bf7960fda4ae805675020874ce4c6",
8
+ "stackwright-pro-dashboard-otter.json": "0b4100afef4946bae259f5759aea872d7b1a25a00af191e1ead32bf9ee304d08",
9
+ "stackwright-pro-data-otter.json": "38ae3a26f064499a5f9773dfea1e2c21f9f358207110224a8e94c19443d236f1",
10
+ "stackwright-pro-designer-otter.json": "46c9fd94a46f1a3f5267f4cb70c3db0adfc28dc7d4ac50256cbe40ea5363b4f0",
11
+ "stackwright-pro-foreman-otter.json": "73f0913de78dfd3da726d9a32c63d84961985109c3ffc5c7522f6c63559609e7",
12
+ "stackwright-pro-page-otter.json": "0973f1b75a481fd177c5ada1a965f8c32e07f97fc28bbbf03b51d9e6d2af2f74",
13
+ "stackwright-pro-theme-otter.json": "2cca6eab4d7ee226d3fca488e908be6ace28dbaea9dae1b111cb76608f0747e6"
14
+ }
15
+ }