enigma-memory 0.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.
Files changed (105) hide show
  1. package/LICENSE +55 -0
  2. package/README.md +379 -0
  3. package/apps/cli/bin/enigma.mjs +1117 -0
  4. package/apps/desktop/src/app.js +1327 -0
  5. package/apps/desktop/src/index.html +1373 -0
  6. package/apps/desktop/src/styles.css +386 -0
  7. package/apps/gateway/bin/enigma-gateway.mjs +52 -0
  8. package/apps/gateway/src/server.mjs +1403 -0
  9. package/apps/native-host/README.md +265 -0
  10. package/apps/native-host/bin/enigma-native-host.mjs +499 -0
  11. package/apps/native-host/manifests/com.enigma.native_host.chrome.json +9 -0
  12. package/apps/native-host/manifests/com.enigma.native_host.edge.json +9 -0
  13. package/apps/native-host/manifests/com.enigma.native_host.firefox.json +9 -0
  14. package/apps/relay/bin/enigma-relay.mjs +52 -0
  15. package/apps/relay/src/server.mjs +1571 -0
  16. package/apps/verifier/bin/enigma-verify.mjs +240 -0
  17. package/deploy/docker-compose.production.example.yml +150 -0
  18. package/deploy/kubernetes/enigma-backend.example.yaml +580 -0
  19. package/package.json +196 -0
  20. package/packages/adapters/PACKAGE_CONTRACT.md +47 -0
  21. package/packages/adapters/src/index.js +183 -0
  22. package/packages/boundary/src/index.js +468 -0
  23. package/packages/connectors/src/index.js +533 -0
  24. package/packages/core/src/index.js +766 -0
  25. package/packages/enterprise/src/index.js +505 -0
  26. package/packages/importers/src/index.js +1083 -0
  27. package/packages/mcp-server/bin/enigma-mcp.mjs +19 -0
  28. package/packages/mcp-server/src/index.js +1185 -0
  29. package/packages/mesh/src/index.js +531 -0
  30. package/packages/metering/PACKAGE_CONTRACT.md +20 -0
  31. package/packages/metering/src/index.js +246 -0
  32. package/packages/optimizer/src/index.js +707 -0
  33. package/packages/passport/src/index.js +651 -0
  34. package/packages/settlement/PACKAGE_CONTRACT.md +28 -0
  35. package/packages/settlement/src/index.js +369 -0
  36. package/packages/storage/PACKAGE_CONTRACT.md +23 -0
  37. package/packages/storage/src/index.js +392 -0
  38. package/packages/vault/src/index.js +904 -0
  39. package/scripts/build-ai-orchestration-plan.mjs +248 -0
  40. package/scripts/build-cloudflare-pages-release-packet.mjs +287 -0
  41. package/scripts/build-cloudflare-token-policy.mjs +239 -0
  42. package/scripts/build-cloudflare-token-request.mjs +314 -0
  43. package/scripts/build-demo-assets.mjs +263 -0
  44. package/scripts/build-edge-backend-workers.mjs +353 -0
  45. package/scripts/build-goal-completion-audit.mjs +398 -0
  46. package/scripts/build-hosted-probe-worker.mjs +191 -0
  47. package/scripts/build-operator-acceptance-packet.mjs +254 -0
  48. package/scripts/build-operator-evidence-starter.mjs +525 -0
  49. package/scripts/build-production-backend-env-kit.mjs +384 -0
  50. package/scripts/build-production-dependency-report.mjs +369 -0
  51. package/scripts/build-production-handoff-packet.mjs +475 -0
  52. package/scripts/build-production-readiness-manifest.mjs +209 -0
  53. package/scripts/build-production-status-board.mjs +297 -0
  54. package/scripts/build-production-storage-migration.mjs +86 -0
  55. package/scripts/build-production-workplan.mjs +371 -0
  56. package/scripts/build-review-packet.mjs +594 -0
  57. package/scripts/check.mjs +419 -0
  58. package/scripts/cloudflare-ops.mjs +1672 -0
  59. package/scripts/cloudflare-secret-env.mjs +128 -0
  60. package/scripts/collect-hosted-backend-live-evidence.mjs +263 -0
  61. package/scripts/infrastructure-readiness.mjs +944 -0
  62. package/scripts/install-enigma-local.mjs +270 -0
  63. package/scripts/memory-optimization-benchmark.mjs +242 -0
  64. package/scripts/monitor-live-endpoints.mjs +358 -0
  65. package/scripts/release-audit.mjs +5588 -0
  66. package/scripts/release-provenance.mjs +250 -0
  67. package/scripts/run-backend-readiness-smoke.mjs +220 -0
  68. package/scripts/validate-backup-restore-drill.mjs +166 -0
  69. package/scripts/validate-cloudflare-credentials.mjs +112 -0
  70. package/scripts/validate-cloudflare-worker-inspect.mjs +179 -0
  71. package/scripts/validate-domain-tls.mjs +248 -0
  72. package/scripts/validate-hosted-backend-live.mjs +319 -0
  73. package/scripts/validate-incident-drill.mjs +221 -0
  74. package/scripts/validate-kms-custody.mjs +235 -0
  75. package/scripts/validate-legal-compliance-approval.mjs +274 -0
  76. package/scripts/validate-monitoring-alerting.mjs +263 -0
  77. package/scripts/validate-network-access-policy.mjs +285 -0
  78. package/scripts/validate-operator-acceptance.mjs +298 -0
  79. package/scripts/validate-production-manifests.mjs +325 -0
  80. package/scripts/validate-public-site-security.mjs +252 -0
  81. package/scripts/validate-security-threat-model.mjs +285 -0
  82. package/scripts/validate-service-settlement.mjs +256 -0
  83. package/scripts/validate-support-sla.mjs +190 -0
  84. package/scripts/validate-tenant-policy-approval.mjs +228 -0
  85. package/scripts/validate-usage-metering.mjs +224 -0
  86. package/scripts/validate-whitepaper-claims.mjs +166 -0
  87. package/specs/boundary-manifest-v1.schema.json +35 -0
  88. package/specs/capsule-v1.schema.json +55 -0
  89. package/specs/claim-boundary-manifest-v1.schema.json +22 -0
  90. package/specs/connector-profile-v1.schema.json +62 -0
  91. package/specs/deletion-tombstone-v1.schema.json +26 -0
  92. package/specs/enterprise-policy-v1.schema.json +59 -0
  93. package/specs/gateway-request-v1.schema.json +32 -0
  94. package/specs/goal-completion-audit-v1.schema.json +70 -0
  95. package/specs/hosted-backend-live-evidence-v1.schema.json +147 -0
  96. package/specs/import-report-v1.schema.json +214 -0
  97. package/specs/infrastructure-readiness-manifest-v1.schema.json +130 -0
  98. package/specs/memory-event-v1.schema.json +42 -0
  99. package/specs/mesh-node-v1.schema.json +126 -0
  100. package/specs/passport-v1.schema.json +50 -0
  101. package/specs/production-handoff-packet-v1.schema.json +149 -0
  102. package/specs/receipt-v1.schema.json +61 -0
  103. package/specs/relay-record-v1.schema.json +43 -0
  104. package/specs/state-checkpoint-v1.schema.json +37 -0
  105. package/specs/trust-bundle-v1.schema.json +56 -0
@@ -0,0 +1,371 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { dirname } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { groupHostedRefsByWorkstream } from './hosted-ref-workstreams.mjs';
6
+
7
+ export const PRODUCTION_WORKPLAN_SCHEMA = 'enigma.production_workplan.v1';
8
+
9
+ const SECRET_RE = /(?:Bearer\s+[A-Za-z0-9._~+/=-]{12,}|Basic\s+[A-Za-z0-9+/=-]{12,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|sk-[A-Za-z0-9_-]{16,}|https?:\/\/[^\s/@]+:[^\s/@]+@|AKIA[0-9A-Z]{16})/iu;
10
+ const LOCAL_PATH_RE = /(?<![A-Za-z])(?:[A-Za-z]:[\\/]|\\\\[^\\/]+[\\/][^\\/]+|\/(?:Users|home)\/[^\s"']+)/u;
11
+
12
+ function parseArgs(argv = process.argv.slice(2)) {
13
+ const out = {
14
+ dependencies: null,
15
+ operatorAcceptance: null,
16
+ hostedRefCatalog: null,
17
+ out: null,
18
+ help: false,
19
+ };
20
+ for (let index = 0; index < argv.length; index += 1) {
21
+ const token = argv[index];
22
+ const readValue = () => {
23
+ const value = argv[index + 1];
24
+ if (typeof value !== 'string' || value.length === 0 || value.startsWith('--')) throw new Error(`${token} requires a value`);
25
+ index += 1;
26
+ return value;
27
+ };
28
+ if (token === '--dependencies') out.dependencies = readValue();
29
+ else if (token === '--operator-acceptance' || token === '--operatorAcceptance') out.operatorAcceptance = readValue();
30
+ else if (token === '--hosted-ref-catalog' || token === '--hostedRefCatalog') out.hostedRefCatalog = readValue();
31
+ else if (token === '--out') out.out = readValue();
32
+ else if (token === '--help' || token === '-h') out.help = true;
33
+ else throw new Error(`Unknown production workplan option: ${token}`);
34
+ }
35
+ return out;
36
+ }
37
+
38
+ function usage() {
39
+ return 'Usage: node scripts/build-production-workplan.mjs --dependencies <production-dependencies.json> [--operator-acceptance <result.json>] [--hosted-ref-catalog <catalog.json>] [--out <file>]\n\nBuilds a public-safe ordered launch workplan from current dependency and operator evidence.\n';
40
+ }
41
+
42
+ async function readJson(path, label) {
43
+ try {
44
+ return JSON.parse(await readFile(path, 'utf8'));
45
+ } catch (error) {
46
+ throw new Error(`Unable to read ${label}`);
47
+ }
48
+ }
49
+
50
+ function assertPublicSafe(value, label = 'production workplan') {
51
+ const text = JSON.stringify(value);
52
+ if (SECRET_RE.test(text)) throw new Error(`${label} contains secret-looking material`);
53
+ if (LOCAL_PATH_RE.test(text)) throw new Error(`${label} contains a local path`);
54
+ }
55
+
56
+ function requireObject(value, label) {
57
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error(`${label} must be an object`);
58
+ assertPublicSafe(value, label);
59
+ return value;
60
+ }
61
+
62
+ function groupsByName(dependencyReport) {
63
+ return new Map((Array.isArray(dependencyReport.groups) ? dependencyReport.groups : []).map((group) => [group.name, group]));
64
+ }
65
+
66
+ function groupStatus(groups, name) {
67
+ const group = groups.get(name) ?? {};
68
+ return {
69
+ ready: group.ready === true,
70
+ blocker_count: Number.isFinite(group.blocker_count) ? group.blocker_count : (Array.isArray(group.blockers) ? group.blockers.length : 0),
71
+ blockers: Array.isArray(group.blockers) ? group.blockers : [],
72
+ evidence: Array.isArray(group.evidence) ? group.evidence : [],
73
+ next_command: typeof group.next_command === 'string' ? group.next_command : null,
74
+ };
75
+ }
76
+
77
+ function actionById(dependencyReport, id) {
78
+ return (Array.isArray(dependencyReport.next_actions) ? dependencyReport.next_actions : []).find((item) => item?.id === id) ?? null;
79
+ }
80
+
81
+ function actionSummary(action) {
82
+ if (!action) return null;
83
+ return {
84
+ id: action.id,
85
+ owner: action.owner ?? 'operator',
86
+ command: action.command ?? null,
87
+ evidence: action.evidence ?? null,
88
+ };
89
+ }
90
+
91
+ function missingHostedRefs(hostedGroup) {
92
+ return hostedGroup.blockers
93
+ .map((item) => /^missing refs\.([A-Za-z0-9_:-]+)$/u.exec(item))
94
+ .filter(Boolean)
95
+ .map((match) => match[1]);
96
+ }
97
+
98
+ function declaredHostedMissingRefCount(hostedGroup, refs) {
99
+ const declared = hostedGroup.blockers
100
+ .map((item) => /^hosted missing refs: (\d+)$/u.exec(item))
101
+ .find(Boolean);
102
+ return declared ? Number(declared[1]) : refs.length;
103
+ }
104
+
105
+ function missingHostedEndpointRefs(hostedGroup) {
106
+ return hostedGroup.blockers
107
+ .map((item) => /^missing (relay|gateway|operator_acceptance)\.ref$/u.exec(item))
108
+ .filter(Boolean)
109
+ .map((match) => `${match[1]}.ref`);
110
+ }
111
+
112
+ function catalogHostedRefKeys(hostedRefCatalog) {
113
+ const refs = hostedRefCatalog?.refs;
114
+ return refs && typeof refs === 'object' ? Object.keys(refs) : [];
115
+ }
116
+
117
+ function expandedMissingHostedRefs(hostedGroup, hostedRefCatalog, blockerRefs, declaredMissingRefCount) {
118
+ const catalogRefs = catalogHostedRefKeys(hostedRefCatalog);
119
+ if (declaredMissingRefCount > blockerRefs.length
120
+ && catalogRefs.length >= declaredMissingRefCount
121
+ && blockerRefs.every((ref) => catalogRefs.includes(ref))) {
122
+ return catalogRefs.slice(0, declaredMissingRefCount);
123
+ }
124
+ return blockerRefs;
125
+ }
126
+
127
+ function hostedStateBlockers(hostedGroup) {
128
+ return hostedGroup.blockers.filter((item) => item === 'hosted_live_ready is false' || item === 'operator acceptance decision is pending');
129
+ }
130
+
131
+ function hostedCatalogFor(refs, hostedRefCatalog) {
132
+ const catalog = hostedRefCatalog?.refs && typeof hostedRefCatalog.refs === 'object' ? hostedRefCatalog.refs : {};
133
+ return Object.fromEntries(refs.map((ref) => {
134
+ const entry = catalog[ref] ?? {};
135
+ return [ref, {
136
+ purpose: typeof entry.purpose === 'string' ? entry.purpose : `Provide verified hosted evidence for ${ref}.`,
137
+ env_names: Array.isArray(entry.env_names) ? entry.env_names : [],
138
+ evidence_command: typeof entry.evidence_command === 'string' ? entry.evidence_command : 'Attach operator evidence and rerun production:manifest.',
139
+ accepted_refs: Array.isArray(entry.accepted_refs) ? entry.accepted_refs : [],
140
+ }];
141
+ }));
142
+ }
143
+
144
+
145
+ function operatorBreakdownFromGroup(operatorGroup, operatorAcceptance) {
146
+ const out = {};
147
+ for (const blocker of operatorGroup.blockers) {
148
+ const match = /^operator blockers ([A-Za-z0-9_:-]+): (\d+)$/u.exec(blocker);
149
+ if (match) out[match[1]] = Number(match[2]);
150
+ }
151
+ if (Object.keys(out).length > 0) return out;
152
+ if (operatorAcceptance?.blocker_breakdown && typeof operatorAcceptance.blocker_breakdown === 'object' && !Array.isArray(operatorAcceptance.blocker_breakdown)) {
153
+ return operatorAcceptance.blocker_breakdown;
154
+ }
155
+ return out;
156
+ }
157
+
158
+ function makePhase({ id, title, ready, owner, prerequisites = [], blockers = [], commands = [], evidence = [], details = {} }) {
159
+ return {
160
+ id,
161
+ title,
162
+ ready: ready === true,
163
+ owner,
164
+ prerequisites,
165
+ blocker_count: blockers.length,
166
+ blockers,
167
+ commands: commands.filter(Boolean),
168
+ evidence,
169
+ details,
170
+ };
171
+ }
172
+
173
+ export function validateProductionWorkplanGraph(phases) {
174
+ const ids = new Set();
175
+ const errors = [];
176
+ for (const phase of phases) {
177
+ if (ids.has(phase.id)) errors.push(`duplicate phase id ${phase.id}`);
178
+ ids.add(phase.id);
179
+ }
180
+ const inbound = new Map(phases.map((phase) => [phase.id, new Set()]));
181
+ const outgoing = new Map(phases.map((phase) => [phase.id, []]));
182
+ for (const phase of phases) {
183
+ for (const prerequisite of phase.prerequisites) {
184
+ if (prerequisite === phase.id) {
185
+ errors.push(`phase ${phase.id} depends on itself`);
186
+ continue;
187
+ }
188
+ if (!ids.has(prerequisite)) {
189
+ errors.push(`phase ${phase.id} has unknown prerequisite ${prerequisite}`);
190
+ continue;
191
+ }
192
+ inbound.get(phase.id).add(prerequisite);
193
+ outgoing.get(prerequisite).push(phase.id);
194
+ }
195
+ }
196
+ if (errors.length > 0) throw new Error(`Invalid production workplan graph: ${errors.join('; ')}`);
197
+ const queue = phases.filter((phase) => inbound.get(phase.id).size === 0).map((phase) => phase.id);
198
+ const executionOrder = [];
199
+ for (let index = 0; index < queue.length; index += 1) {
200
+ const id = queue[index];
201
+ executionOrder.push(id);
202
+ for (const target of outgoing.get(id)) {
203
+ const targetInbound = inbound.get(target);
204
+ targetInbound.delete(id);
205
+ if (targetInbound.size === 0) queue.push(target);
206
+ }
207
+ }
208
+ if (executionOrder.length !== phases.length) {
209
+ const unresolved = phases.filter((phase) => !executionOrder.includes(phase.id)).map((phase) => phase.id);
210
+ throw new Error(`Invalid production workplan graph: cycle involving ${unresolved.join(', ')}`);
211
+ }
212
+ return executionOrder;
213
+ }
214
+
215
+ export function buildProductionWorkplan(inputs = {}, options = {}) {
216
+ const dependencyReport = requireObject(inputs.dependencyReport, 'dependency report');
217
+ if (dependencyReport.schema !== 'enigma.production_dependency_report.v1') throw new Error('dependency report schema mismatch');
218
+ const operatorAcceptance = inputs.operatorAcceptance === undefined || inputs.operatorAcceptance === null ? null : requireObject(inputs.operatorAcceptance, 'operator acceptance result');
219
+ const hostedRefCatalog = inputs.hostedRefCatalog === undefined || inputs.hostedRefCatalog === null ? null : requireObject(inputs.hostedRefCatalog, 'hosted ref catalog');
220
+ if (operatorAcceptance !== null && operatorAcceptance.schema !== 'enigma.operator_acceptance_result.v1') throw new Error('operator acceptance schema mismatch');
221
+ if (hostedRefCatalog !== null && hostedRefCatalog.schema !== 'enigma.operator_hosted_ref_catalog.v1') throw new Error('hosted ref catalog schema mismatch');
222
+
223
+ const groups = groupsByName(dependencyReport);
224
+ const credentials = groupStatus(groups, 'cloudflare_credentials');
225
+ const worker = groupStatus(groups, 'cloudflare_worker_permission');
226
+ const hosted = groupStatus(groups, 'hosted_backend_live');
227
+ const operator = groupStatus(groups, 'operator_acceptance');
228
+ const release = groupStatus(groups, 'release_gates');
229
+ const staticSite = groupStatus(groups, 'static_site');
230
+ const whitepaper = groupStatus(groups, 'whitepaper_claims');
231
+ const blockerRefs = missingHostedRefs(hosted);
232
+ const declaredMissingRefCount = declaredHostedMissingRefCount(hosted, blockerRefs);
233
+ const refs = expandedMissingHostedRefs(hosted, hostedRefCatalog, blockerRefs, declaredMissingRefCount);
234
+ const endpointRefs = missingHostedEndpointRefs(hosted);
235
+ const stateBlockers = hostedStateBlockers(hosted);
236
+
237
+ const phases = [
238
+ makePhase({
239
+ id: 'cloudflare_credentials',
240
+ title: 'Create and inject Cloudflare deployment credentials',
241
+ ready: credentials.ready,
242
+ owner: 'operator',
243
+ blockers: credentials.blockers,
244
+ commands: [credentials.next_command, actionSummary(actionById(dependencyReport, 'create-cloudflare-token'))?.command, 'npm run production:cloudflare-credentials -- --out .enigma/cloudflare-credentials-current.json'],
245
+ evidence: credentials.evidence,
246
+ details: { token_value_must_not_be_shared: true, required_env_keys: ['CLOUDFLARE_API_TOKEN', 'CLOUDFLARE_ACCOUNT_ID'] },
247
+ }),
248
+ makePhase({
249
+ id: 'cloudflare_worker_permission',
250
+ title: 'Verify Cloudflare Worker visibility and optional hosted probe deploy path',
251
+ ready: worker.ready,
252
+ owner: 'operator-or-ai-with-token',
253
+ prerequisites: ['cloudflare_credentials'],
254
+ blockers: worker.blockers,
255
+ commands: [worker.next_command, actionSummary(actionById(dependencyReport, 'optional-standalone-worker-probe'))?.command],
256
+ evidence: worker.evidence,
257
+ details: { standalone_probe_is_not_hosted_backend_evidence: true },
258
+ }),
259
+ makePhase({
260
+ id: 'release_gates',
261
+ title: 'Keep local release, whitepaper, static-site, and package gates green',
262
+ ready: release.ready && staticSite.ready && whitepaper.ready,
263
+ owner: 'operator-or-reviewer',
264
+ prerequisites: [],
265
+ blockers: [...release.blockers, ...staticSite.blockers, ...whitepaper.blockers],
266
+ commands: [release.next_command, staticSite.next_command, whitepaper.next_command],
267
+ evidence: [...release.evidence, ...staticSite.evidence, ...whitepaper.evidence],
268
+ details: { release_gates_ready: release.ready, static_site_ready: staticSite.ready, whitepaper_ready: whitepaper.ready },
269
+ }),
270
+ makePhase({
271
+ id: 'hosted_backend_refs',
272
+ title: 'Provision relay/gateway and required hosted evidence refs',
273
+ ready: hosted.ready,
274
+ owner: 'operator',
275
+ prerequisites: ['cloudflare_credentials'],
276
+ blockers: hosted.blockers,
277
+ commands: [actionSummary(actionById(dependencyReport, 'generate-operator-evidence-starter'))?.command, actionSummary(actionById(dependencyReport, 'generate-backend-env-kit'))?.command, actionSummary(actionById(dependencyReport, 'provision-hosted-backend'))?.command, hosted.next_command, actionSummary(actionById(dependencyReport, 'validate-hosted-backend-live-evidence'))?.command],
278
+ evidence: hosted.evidence,
279
+ details: {
280
+ missing_ref_count: declaredMissingRefCount,
281
+ listed_missing_ref_count: refs.length,
282
+ blocker_listed_missing_ref_count: blockerRefs.length,
283
+ unlisted_missing_ref_count: Math.max(0, declaredMissingRefCount - refs.length),
284
+ missing_refs: refs,
285
+ missing_ref_groups: groupHostedRefsByWorkstream(refs),
286
+ missing_endpoint_refs: endpointRefs,
287
+ hosted_state_blockers: stateBlockers,
288
+ hosted_ref_catalog: hostedCatalogFor(refs, hostedRefCatalog),
289
+ },
290
+ }),
291
+ makePhase({
292
+ id: 'operator_acceptance',
293
+ title: 'Complete operator acceptance packet with go decision and zero blockers',
294
+ ready: operator.ready,
295
+ owner: 'operator-or-reviewer',
296
+ prerequisites: ['hosted_backend_refs', 'release_gates'],
297
+ blockers: operator.blockers,
298
+ commands: [actionSummary(actionById(dependencyReport, 'generate-operator-evidence-starter'))?.command, operator.next_command, actionSummary(actionById(dependencyReport, 'complete-operator-acceptance'))?.command],
299
+ evidence: operator.evidence,
300
+ details: {
301
+ decision: operatorAcceptance?.decision ?? null,
302
+ blocker_breakdown: operatorBreakdownFromGroup(operator, operatorAcceptance),
303
+ },
304
+ }),
305
+ makePhase({
306
+ id: 'final_release_verification',
307
+ title: 'Rerun release gates and goal/dependency audits after external blockers clear',
308
+ ready: dependencyReport.launch_ready === true,
309
+ owner: 'operator-or-reviewer',
310
+ prerequisites: ['cloudflare_credentials', 'cloudflare_worker_permission', 'hosted_backend_refs', 'operator_acceptance', 'release_gates'],
311
+ blockers: dependencyReport.launch_ready === true ? [] : ['launch_ready is false'],
312
+ commands: [release.next_command, staticSite.next_command, whitepaper.next_command, 'npm run production:goal-audit -- --site <public-site-dir> --domain enigmamemory.com --release-audit .enigma/release-audit-current.json', 'npm run production:dependencies -- --goal-audit .enigma/goal-audit-current.json --release-audit .enigma/release-audit-current.json --worker-inspect .enigma/worker-inspect-validation-current.json --whitepaper .enigma/whitepaper-claims-current.json --cloudflare-credentials .enigma/cloudflare-credentials-current.json --edge-deploy .enigma/edge-backend-deployment-current.json --edge-live .enigma/edge-backend-bootstrap-live-current.json --storage-bootstrap .enigma/cloudflare-storage-bootstrap-current.json'],
313
+ evidence: [...release.evidence, ...staticSite.evidence, ...whitepaper.evidence],
314
+ details: { goal_complete: dependencyReport.goal_complete === true, launch_ready: dependencyReport.launch_ready === true },
315
+ }),
316
+ ];
317
+ const executionOrder = validateProductionWorkplanGraph(phases);
318
+
319
+ const firstBlocked = phases.find((phase) => phase.ready !== true) ?? null;
320
+ const report = {
321
+ schema: PRODUCTION_WORKPLAN_SCHEMA,
322
+ generated_at: options.generated_at ?? new Date().toISOString(),
323
+ status: firstBlocked === null ? 'ready' : 'blocked',
324
+ launch_ready: dependencyReport.launch_ready === true,
325
+ dependency_status: dependencyReport.status,
326
+ blocked_phase_count: phases.filter((phase) => phase.ready !== true).length,
327
+ phase_count: phases.length,
328
+ next_phase_id: firstBlocked?.id ?? null,
329
+ execution_order: executionOrder,
330
+ phases,
331
+ evidence_inputs: {
332
+ dependency_generated_at: dependencyReport.generated_at ?? null,
333
+ operator_acceptance_generated_at: operatorAcceptance?.generated_at ?? null,
334
+ hosted_ref_catalog_generated_at: hostedRefCatalog?.generated_at ?? null,
335
+ },
336
+ claim_boundary: [
337
+ 'This workplan is an ordered public-safe execution plan generated from current evidence; it does not create accounts, deploy infrastructure, approve operators, or certify launch readiness.',
338
+ 'Token values, account ids, credential-bearing URLs, raw memory, prompts, transcripts, provider responses, and private key material must stay outside this artifact.',
339
+ 'launch_ready:true requires every phase to be ready and the dependency report to be launch_ready:true with direct current evidence.',
340
+ ],
341
+ };
342
+ assertPublicSafe(report);
343
+ return report;
344
+ }
345
+
346
+ export async function main(argv = process.argv.slice(2)) {
347
+ const args = parseArgs(argv);
348
+ if (args.help) return { text: usage(), status: 0 };
349
+ if (!args.dependencies) throw new Error('--dependencies is required');
350
+ const report = buildProductionWorkplan({
351
+ dependencyReport: await readJson(args.dependencies, 'dependency report'),
352
+ operatorAcceptance: args.operatorAcceptance ? await readJson(args.operatorAcceptance, 'operator acceptance result') : null,
353
+ hostedRefCatalog: args.hostedRefCatalog ? await readJson(args.hostedRefCatalog, 'hosted ref catalog') : null,
354
+ });
355
+ const json = `${JSON.stringify(report, null, 2)}\n`;
356
+ if (args.out) {
357
+ await mkdir(dirname(args.out), { recursive: true });
358
+ await writeFile(args.out, json, 'utf8');
359
+ }
360
+ return { text: json, status: report.launch_ready ? 0 : 1 };
361
+ }
362
+
363
+ if (fileURLToPath(import.meta.url) === process.argv[1]) {
364
+ main().then(({ text, status }) => {
365
+ process.stdout.write(text);
366
+ process.exitCode = status;
367
+ }).catch((error) => {
368
+ process.stdout.write(`${JSON.stringify({ schema: PRODUCTION_WORKPLAN_SCHEMA, status: 'blocked', launch_ready: false, blockers: [error.message] }, null, 2)}\n`);
369
+ process.exitCode = 1;
370
+ });
371
+ }