@josfox/jos 4.0.7 → 4.1.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.
@@ -1,244 +1,244 @@
1
- /**
2
- * JOS RUN Command - Execute .jos artifacts
3
- * Complies with JOSFOXAI MAGIC contract
4
- * Integrity Strategy: Detached Manifest (.sig.json)
5
- * Format version v0.0.7 — Specification maturity v0.1.0 (Alpha)
6
- */
7
-
8
- const fs = require('fs');
9
- const path = require('path');
10
- const { execSync, spawn } = require('child_process');
11
- const crypto = require('crypto');
12
-
13
- // AURORA colors
14
- const C = {
15
- reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
16
- purple: '\x1b[38;5;135m', cyan: '\x1b[38;5;51m',
17
- green: '\x1b[38;5;78m', red: '\x1b[38;5;196m',
18
- yellow: '\x1b[38;5;220m', white: '\x1b[38;5;255m',
19
- gray: '\x1b[38;5;245m', blue: '\x1b[38;5;39m'
20
- };
21
-
22
- // Witness Logging
23
- function logWitness(home, eventType, data) {
24
- const runId = global.JOS_RUN_ID || new Date().toISOString().replace(/[:.]/g, '-');
25
- global.JOS_RUN_ID = runId;
26
-
27
- const runDir = path.join(home, 'runs', runId);
28
- if (!fs.existsSync(runDir)) fs.mkdirSync(runDir, { recursive: true });
29
-
30
- const event = {
31
- timestamp: new Date().toISOString(),
32
- type: `run:${eventType}`,
33
- ...data
34
- };
35
-
36
- fs.appendFileSync(path.join(runDir, 'events.jsonl'), JSON.stringify(event) + '\n');
37
- }
38
-
39
- // Compute SHA-256 integrity
40
- function computeIntegrity(content) {
41
- return crypto.createHash('sha256').update(content).digest('hex');
42
- }
43
-
44
- // Verify Integrity using Detached Manifest
45
- function verifyIntegrity(artifactPath, content, artifact) {
46
- const integrityRef = artifact.security?.integrity_ref;
47
- if (!integrityRef) return { valid: true, warning: "open (no integrity_ref)" };
48
-
49
- const manifestPath = path.resolve(path.dirname(artifactPath), integrityRef);
50
- if (!fs.existsSync(manifestPath)) {
51
- return { valid: false, error: `Manifest not found at ${manifestPath}` };
52
- }
53
-
54
- let manifest;
55
- try {
56
- manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
57
- } catch (e) {
58
- return { valid: false, error: "Invalid manifest JSON" };
59
- }
60
-
61
- const actualHash = computeIntegrity(content);
62
- if (actualHash !== manifest.artifact_sha256) {
63
- return {
64
- valid: false,
65
- error: `Hash mismatch. Expected: ${manifest.artifact_sha256.substring(0, 16)}..., Got: ${actualHash.substring(0, 16)}...`
66
- };
67
- }
68
-
69
- return { valid: true, verified: true, hash: actualHash };
70
- }
71
-
72
- exports.execute = async (args, home) => {
73
- const target = args[0];
74
- const dryRun = args.includes('--dry-run');
75
- const insecure = args.includes('--insecure');
76
-
77
- if (args.includes('--help') || !target) {
78
- console.log(`
79
- ${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}
80
- ${C.bold}JOS RUN${C.reset} // Execute .jos artifacts
81
- ${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}
82
-
83
- ${C.bold}Usage:${C.reset}
84
- jos run <file.jos> [options]
85
-
86
- ${C.bold}Options:${C.reset}
87
- --flow <name> Flow to execute (default: main)
88
- --dry-run Simulate without executing
89
- --insecure Skip integrity verification
90
-
91
- ${C.bold}Example:${C.reset}
92
- jos run orchestration.jos --flow publish_all --dry-run
93
- `);
94
- return;
95
- }
96
-
97
- let artifactPath = path.resolve(target);
98
- if (!fs.existsSync(artifactPath)) {
99
- if (fs.existsSync(path.join(home, 'artifacts', target))) {
100
- artifactPath = path.join(home, 'artifacts', target);
101
- } else {
102
- console.log(`${C.red}✖ Artifact not found:${C.reset} ${target}`);
103
- process.exit(1);
104
- }
105
- }
106
-
107
- const content = fs.readFileSync(artifactPath, 'utf8');
108
- const artifact = JSON.parse(content);
109
-
110
- // Init Witness
111
- logWitness(home, 'start', { artifact: artifactPath, dryRun: dryRun });
112
-
113
- // Header
114
- console.log(`\n${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}`);
115
- console.log(`${C.cyan}${C.bold}JOS RUN${C.reset} // ${C.gray}JOSFOXAI MAGIC Runtime${C.reset}`);
116
- console.log(`${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n`);
117
-
118
- // Mode indicator
119
- if (dryRun) {
120
- console.log(`${C.yellow}${C.bold}⚡ DRY RUN MODE${C.reset} ${C.gray}— No commands will be executed${C.reset}\n`);
121
- }
122
-
123
- // Artifact info
124
- console.log(`${C.cyan}📦 Artifact:${C.reset} ${artifact.meta?.name || path.basename(artifactPath)}`);
125
- console.log(`${C.cyan}📄 File:${C.reset} ${path.basename(artifactPath)}`);
126
- console.log(`${C.cyan}🆔 ID:${C.reset} ${artifact.id_jos || 'N/A'}`);
127
-
128
- // Integrity verification
129
- if (!insecure) {
130
- const integrity = verifyIntegrity(artifactPath, content, artifact);
131
- if (!integrity.valid) {
132
- console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.red}FAILED - ${integrity.error}${C.reset}`);
133
- logWitness(home, 'integrity_failed', { error: integrity.error });
134
- process.exit(1);
135
- } else if (integrity.verified) {
136
- console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.green}✓ Verified${C.reset} ${C.gray}(${integrity.hash.substring(0, 16)}...)${C.reset}`);
137
- logWitness(home, 'integrity_verified', { hash: integrity.hash });
138
- } else {
139
- console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.yellow}⚠ ${integrity.warning}${C.reset}`);
140
- }
141
- } else {
142
- console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.yellow}⚠ Skipped (--insecure)${C.reset}`);
143
- }
144
-
145
- // MAGIC validation
146
- const hasMagic = artifact.intention && artifact.guardrails && artifact.capabilities;
147
- console.log(`${C.cyan}✨ MAGIC:${C.reset} ${hasMagic ? C.green + '✓ Valid' : C.yellow + '⚠ Partial'}${C.reset}`);
148
-
149
- // Intention
150
- if (artifact.intention?.objective) {
151
- console.log(`${C.cyan}🎯 Intention:${C.reset} ${artifact.intention.objective}`);
152
- }
153
-
154
- // Guardrails
155
- if (artifact.guardrails?.avoid?.length > 0) {
156
- console.log(`${C.cyan}🛡️ Guardrails:${C.reset} ${artifact.guardrails.avoid.join(', ')}`);
157
- }
158
-
159
- // Flow selection
160
- const flowName = args.includes('--flow') ? args[args.indexOf('--flow') + 1] : 'main';
161
- const flow = artifact.orchestration?.flows?.[flowName] ||
162
- artifact.orchestration?.pipelines?.[flowName];
163
-
164
- if (!flow) {
165
- console.log(`\n${C.red}✖ Flow '${flowName}' not found.${C.reset}`);
166
- const available = [
167
- ...Object.keys(artifact.orchestration?.flows || {}),
168
- ...Object.keys(artifact.orchestration?.pipelines || {})
169
- ];
170
- if (available.length > 0) {
171
- console.log(`${C.gray}Available flows: ${available.join(', ')}${C.reset}`);
172
- }
173
- process.exit(1);
174
- }
175
-
176
- // Execution plan
177
- console.log(`\n${C.cyan}▶ Flow:${C.reset} ${C.bold}${flowName}${C.reset}`);
178
- if (flow.description) {
179
- console.log(`${C.gray} ${flow.description}${C.reset}`);
180
- }
181
- console.log(`${C.gray} Steps: ${flow.steps?.join(' → ') || 'none'}${C.reset}\n`);
182
-
183
- // Execute steps
184
- let stepIndex = 0;
185
- for (const stepName of flow.steps || []) {
186
- stepIndex++;
187
- const def = artifact.orchestration.definitions?.[stepName];
188
-
189
- if (!def) {
190
- console.log(`${C.red} [${stepIndex}] ✖ ${stepName}: Definition not found${C.reset}`);
191
- logWitness(home, 'step_error', { step: stepName, error: 'definition not found' });
192
- continue;
193
- }
194
-
195
- logWitness(home, 'step_start', { step: stepName, type: def.type, index: stepIndex });
196
-
197
- const typeIcon = def.type === 'shell' ? '⚡' : def.type === 'jos' ? '📦' : '●';
198
-
199
- if (dryRun) {
200
- console.log(`${C.yellow} [${stepIndex}] ${typeIcon} ${stepName}${C.reset}`);
201
- if (def.description) console.log(`${C.gray} ${def.description}${C.reset}`);
202
- if (def.type === 'shell') {
203
- const cmdPreview = def.command.length > 60 ? def.command.substring(0, 60) + '...' : def.command;
204
- console.log(`${C.dim} $ ${cmdPreview}${C.reset}`);
205
- } else if (def.type === 'jos') {
206
- console.log(`${C.dim} → ${def.artifact}${C.reset}`);
207
- }
208
- logWitness(home, 'step_dry_run', { step: stepName });
209
- continue;
210
- }
211
-
212
- // Real execution
213
- console.log(`${C.blue} [${stepIndex}] ${typeIcon} ${stepName}...${C.reset}`);
214
-
215
- try {
216
- if (def.type === 'shell') {
217
- execSync(def.command, { stdio: 'inherit', shell: '/bin/bash' });
218
- console.log(`${C.green} ✓ Complete${C.reset}`);
219
- } else if (def.type === 'jos') {
220
- console.log(`${C.purple} Running sub-artifact: ${def.artifact}${C.reset}`);
221
- const subPath = path.resolve(path.dirname(artifactPath), def.artifact);
222
- const binJos = process.argv[1];
223
- execSync(`${process.execPath} "${binJos}" run "${subPath}" ${insecure ? '--insecure' : ''} --flow main`, {
224
- stdio: 'inherit'
225
- });
226
- }
227
- logWitness(home, 'step_complete', { step: stepName, success: true });
228
- } catch (e) {
229
- console.log(`${C.red} ✖ Failed: ${e.message}${C.reset}`);
230
- logWitness(home, 'step_failed', { step: stepName, error: e.message });
231
- logWitness(home, 'run_failed', { lastStep: stepName });
232
- process.exit(1);
233
- }
234
- }
235
-
236
- // Success
237
- console.log(`\n${C.green}${C.bold}✓ ${dryRun ? 'Dry run complete' : 'Execution complete'}${C.reset}`);
238
- if (artifact.intention?.success_criteria) {
239
- console.log(`${C.gray} Success criteria: ${artifact.intention.success_criteria}${C.reset}`);
240
- }
241
- console.log('');
242
-
243
- logWitness(home, 'success', { dryRun: dryRun, stepsExecuted: stepIndex });
244
- };
1
+ /**
2
+ * JOS RUN Command - Execute .jos artifacts
3
+ * Complies with JOSFOXAI MAGIC contract
4
+ * Integrity Strategy: Detached Manifest (.sig.json)
5
+ * Format version v0.0.7 — Specification maturity v0.1.0 (Alpha)
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const { execSync, spawn } = require('child_process');
11
+ const crypto = require('crypto');
12
+
13
+ // AURORA colors
14
+ const C = {
15
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
16
+ purple: '\x1b[38;5;135m', cyan: '\x1b[38;5;51m',
17
+ green: '\x1b[38;5;78m', red: '\x1b[38;5;196m',
18
+ yellow: '\x1b[38;5;220m', white: '\x1b[38;5;255m',
19
+ gray: '\x1b[38;5;245m', blue: '\x1b[38;5;39m'
20
+ };
21
+
22
+ // Witness Logging
23
+ function logWitness(home, eventType, data) {
24
+ const runId = global.JOS_RUN_ID || new Date().toISOString().replace(/[:.]/g, '-');
25
+ global.JOS_RUN_ID = runId;
26
+
27
+ const runDir = path.join(home, 'runs', runId);
28
+ if (!fs.existsSync(runDir)) fs.mkdirSync(runDir, { recursive: true });
29
+
30
+ const event = {
31
+ timestamp: new Date().toISOString(),
32
+ type: `run:${eventType}`,
33
+ ...data
34
+ };
35
+
36
+ fs.appendFileSync(path.join(runDir, 'events.jsonl'), JSON.stringify(event) + '\n');
37
+ }
38
+
39
+ // Compute SHA-256 integrity
40
+ function computeIntegrity(content) {
41
+ return crypto.createHash('sha256').update(content).digest('hex');
42
+ }
43
+
44
+ // Verify Integrity using Detached Manifest
45
+ function verifyIntegrity(artifactPath, content, artifact) {
46
+ const integrityRef = artifact.security?.integrity_ref;
47
+ if (!integrityRef) return { valid: true, warning: "open (no integrity_ref)" };
48
+
49
+ const manifestPath = path.resolve(path.dirname(artifactPath), integrityRef);
50
+ if (!fs.existsSync(manifestPath)) {
51
+ return { valid: false, error: `Manifest not found at ${manifestPath}` };
52
+ }
53
+
54
+ let manifest;
55
+ try {
56
+ manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
57
+ } catch (e) {
58
+ return { valid: false, error: "Invalid manifest JSON" };
59
+ }
60
+
61
+ const actualHash = computeIntegrity(content);
62
+ if (actualHash !== manifest.artifact_sha256) {
63
+ return {
64
+ valid: false,
65
+ error: `Hash mismatch. Expected: ${manifest.artifact_sha256.substring(0, 16)}..., Got: ${actualHash.substring(0, 16)}...`
66
+ };
67
+ }
68
+
69
+ return { valid: true, verified: true, hash: actualHash };
70
+ }
71
+
72
+ exports.execute = async (args, home) => {
73
+ const target = args[0];
74
+ const dryRun = args.includes('--dry-run');
75
+ const insecure = args.includes('--insecure');
76
+
77
+ if (args.includes('--help') || !target) {
78
+ console.log(`
79
+ ${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}
80
+ ${C.bold}JOS RUN${C.reset} // Execute .jos artifacts
81
+ ${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}
82
+
83
+ ${C.bold}Usage:${C.reset}
84
+ jos run <file.jos> [options]
85
+
86
+ ${C.bold}Options:${C.reset}
87
+ --flow <name> Flow to execute (default: main)
88
+ --dry-run Simulate without executing
89
+ --insecure Skip integrity verification
90
+
91
+ ${C.bold}Example:${C.reset}
92
+ jos run orchestration.jos --flow publish_all --dry-run
93
+ `);
94
+ return;
95
+ }
96
+
97
+ let artifactPath = path.resolve(target);
98
+ if (!fs.existsSync(artifactPath)) {
99
+ if (fs.existsSync(path.join(home, 'artifacts', target))) {
100
+ artifactPath = path.join(home, 'artifacts', target);
101
+ } else {
102
+ console.log(`${C.red}✖ Artifact not found:${C.reset} ${target}`);
103
+ process.exit(1);
104
+ }
105
+ }
106
+
107
+ const content = fs.readFileSync(artifactPath, 'utf8');
108
+ const artifact = JSON.parse(content);
109
+
110
+ // Init Witness
111
+ logWitness(home, 'start', { artifact: artifactPath, dryRun: dryRun });
112
+
113
+ // Header
114
+ console.log(`\n${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}`);
115
+ console.log(`${C.cyan}${C.bold}JOS RUN${C.reset} // ${C.gray}JOSFOXAI MAGIC Runtime${C.reset}`);
116
+ console.log(`${C.purple}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n`);
117
+
118
+ // Mode indicator
119
+ if (dryRun) {
120
+ console.log(`${C.yellow}${C.bold}⚡ DRY RUN MODE${C.reset} ${C.gray}— No commands will be executed${C.reset}\n`);
121
+ }
122
+
123
+ // Artifact info
124
+ console.log(`${C.cyan}📦 Artifact:${C.reset} ${artifact.meta?.name || path.basename(artifactPath)}`);
125
+ console.log(`${C.cyan}📄 File:${C.reset} ${path.basename(artifactPath)}`);
126
+ console.log(`${C.cyan}🆔 ID:${C.reset} ${artifact.id_jos || 'N/A'}`);
127
+
128
+ // Integrity verification
129
+ if (!insecure) {
130
+ const integrity = verifyIntegrity(artifactPath, content, artifact);
131
+ if (!integrity.valid) {
132
+ console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.red}FAILED - ${integrity.error}${C.reset}`);
133
+ logWitness(home, 'integrity_failed', { error: integrity.error });
134
+ process.exit(1);
135
+ } else if (integrity.verified) {
136
+ console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.green}✓ Verified${C.reset} ${C.gray}(${integrity.hash.substring(0, 16)}...)${C.reset}`);
137
+ logWitness(home, 'integrity_verified', { hash: integrity.hash });
138
+ } else {
139
+ console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.yellow}⚠ ${integrity.warning}${C.reset}`);
140
+ }
141
+ } else {
142
+ console.log(`${C.cyan}🔐 Integrity:${C.reset} ${C.yellow}⚠ Skipped (--insecure)${C.reset}`);
143
+ }
144
+
145
+ // MAGIC validation
146
+ const hasMagic = artifact.intention && artifact.guardrails && artifact.capabilities;
147
+ console.log(`${C.cyan}✨ MAGIC:${C.reset} ${hasMagic ? C.green + '✓ Valid' : C.yellow + '⚠ Partial'}${C.reset}`);
148
+
149
+ // Intention
150
+ if (artifact.intention?.objective) {
151
+ console.log(`${C.cyan}🎯 Intention:${C.reset} ${artifact.intention.objective}`);
152
+ }
153
+
154
+ // Guardrails
155
+ if (artifact.guardrails?.avoid?.length > 0) {
156
+ console.log(`${C.cyan}🛡️ Guardrails:${C.reset} ${artifact.guardrails.avoid.join(', ')}`);
157
+ }
158
+
159
+ // Flow selection
160
+ const flowName = args.includes('--flow') ? args[args.indexOf('--flow') + 1] : 'main';
161
+ const flow = artifact.orchestration?.flows?.[flowName] ||
162
+ artifact.orchestration?.pipelines?.[flowName];
163
+
164
+ if (!flow) {
165
+ console.log(`\n${C.red}✖ Flow '${flowName}' not found.${C.reset}`);
166
+ const available = [
167
+ ...Object.keys(artifact.orchestration?.flows || {}),
168
+ ...Object.keys(artifact.orchestration?.pipelines || {})
169
+ ];
170
+ if (available.length > 0) {
171
+ console.log(`${C.gray}Available flows: ${available.join(', ')}${C.reset}`);
172
+ }
173
+ process.exit(1);
174
+ }
175
+
176
+ // Execution plan
177
+ console.log(`\n${C.cyan}▶ Flow:${C.reset} ${C.bold}${flowName}${C.reset}`);
178
+ if (flow.description) {
179
+ console.log(`${C.gray} ${flow.description}${C.reset}`);
180
+ }
181
+ console.log(`${C.gray} Steps: ${flow.steps?.join(' → ') || 'none'}${C.reset}\n`);
182
+
183
+ // Execute steps
184
+ let stepIndex = 0;
185
+ for (const stepName of flow.steps || []) {
186
+ stepIndex++;
187
+ const def = artifact.orchestration.definitions?.[stepName];
188
+
189
+ if (!def) {
190
+ console.log(`${C.red} [${stepIndex}] ✖ ${stepName}: Definition not found${C.reset}`);
191
+ logWitness(home, 'step_error', { step: stepName, error: 'definition not found' });
192
+ continue;
193
+ }
194
+
195
+ logWitness(home, 'step_start', { step: stepName, type: def.type, index: stepIndex });
196
+
197
+ const typeIcon = def.type === 'shell' ? '⚡' : def.type === 'jos' ? '📦' : '●';
198
+
199
+ if (dryRun) {
200
+ console.log(`${C.yellow} [${stepIndex}] ${typeIcon} ${stepName}${C.reset}`);
201
+ if (def.description) console.log(`${C.gray} ${def.description}${C.reset}`);
202
+ if (def.type === 'shell') {
203
+ const cmdPreview = def.command.length > 60 ? def.command.substring(0, 60) + '...' : def.command;
204
+ console.log(`${C.dim} $ ${cmdPreview}${C.reset}`);
205
+ } else if (def.type === 'jos') {
206
+ console.log(`${C.dim} → ${def.artifact}${C.reset}`);
207
+ }
208
+ logWitness(home, 'step_dry_run', { step: stepName });
209
+ continue;
210
+ }
211
+
212
+ // Real execution
213
+ console.log(`${C.blue} [${stepIndex}] ${typeIcon} ${stepName}...${C.reset}`);
214
+
215
+ try {
216
+ if (def.type === 'shell') {
217
+ execSync(def.command, { stdio: 'inherit' });
218
+ console.log(`${C.green} ✓ Complete${C.reset}`);
219
+ } else if (def.type === 'jos') {
220
+ console.log(`${C.purple} Running sub-artifact: ${def.artifact}${C.reset}`);
221
+ const subPath = path.resolve(path.dirname(artifactPath), def.artifact);
222
+ const binJos = process.argv[1];
223
+ execSync(`${process.execPath} "${binJos}" run "${subPath}" ${insecure ? '--insecure' : ''} --flow main`, {
224
+ stdio: 'inherit'
225
+ });
226
+ }
227
+ logWitness(home, 'step_complete', { step: stepName, success: true });
228
+ } catch (e) {
229
+ console.log(`${C.red} ✖ Failed: ${e.message}${C.reset}`);
230
+ logWitness(home, 'step_failed', { step: stepName, error: e.message });
231
+ logWitness(home, 'run_failed', { lastStep: stepName });
232
+ process.exit(1);
233
+ }
234
+ }
235
+
236
+ // Success
237
+ console.log(`\n${C.green}${C.bold}✓ ${dryRun ? 'Dry run complete' : 'Execution complete'}${C.reset}`);
238
+ if (artifact.intention?.success_criteria) {
239
+ console.log(`${C.gray} Success criteria: ${artifact.intention.success_criteria}${C.reset}`);
240
+ }
241
+ console.log('');
242
+
243
+ logWitness(home, 'success', { dryRun: dryRun, stepsExecuted: stepIndex });
244
+ };