paracosm 0.7.409 → 0.7.431

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 (146) hide show
  1. package/README.md +79 -14
  2. package/dist/cli/compile.d.ts +1 -1
  3. package/dist/cli/compile.js +4 -4
  4. package/dist/cli/fetch-seed-url.d.ts +48 -0
  5. package/dist/cli/fetch-seed-url.d.ts.map +1 -0
  6. package/dist/cli/fetch-seed-url.js +109 -0
  7. package/dist/cli/fetch-seed-url.js.map +1 -0
  8. package/dist/cli/fork-preconditions.d.ts +17 -0
  9. package/dist/cli/fork-preconditions.d.ts.map +1 -0
  10. package/dist/cli/fork-preconditions.js +51 -0
  11. package/dist/cli/fork-preconditions.js.map +1 -0
  12. package/dist/cli/init-templates.d.ts +43 -0
  13. package/dist/cli/init-templates.d.ts.map +1 -0
  14. package/dist/cli/init-templates.js +141 -0
  15. package/dist/cli/init-templates.js.map +1 -0
  16. package/dist/cli/init.d.ts +46 -0
  17. package/dist/cli/init.d.ts.map +1 -0
  18. package/dist/cli/init.js +207 -0
  19. package/dist/cli/init.js.map +1 -0
  20. package/dist/cli/pair-runner.d.ts +25 -2
  21. package/dist/cli/pair-runner.d.ts.map +1 -1
  22. package/dist/cli/pair-runner.js +141 -5
  23. package/dist/cli/pair-runner.js.map +1 -1
  24. package/dist/cli/quickstart-routes.d.ts +35 -0
  25. package/dist/cli/quickstart-routes.d.ts.map +1 -0
  26. package/dist/cli/quickstart-routes.js +100 -0
  27. package/dist/cli/quickstart-routes.js.map +1 -0
  28. package/dist/cli/run.js +8 -0
  29. package/dist/cli/run.js.map +1 -1
  30. package/dist/cli/server/enrich-run-record.d.ts +22 -0
  31. package/dist/cli/server/enrich-run-record.d.ts.map +1 -0
  32. package/dist/cli/server/enrich-run-record.js +27 -0
  33. package/dist/cli/server/enrich-run-record.js.map +1 -0
  34. package/dist/cli/server/routes/platform-api.d.ts +19 -3
  35. package/dist/cli/server/routes/platform-api.d.ts.map +1 -1
  36. package/dist/cli/server/routes/platform-api.js +174 -5
  37. package/dist/cli/server/routes/platform-api.js.map +1 -1
  38. package/dist/cli/server/run-history-store.d.ts +27 -1
  39. package/dist/cli/server/run-history-store.d.ts.map +1 -1
  40. package/dist/cli/server/run-history-store.js +5 -0
  41. package/dist/cli/server/run-history-store.js.map +1 -1
  42. package/dist/cli/server/run-record.d.ts +13 -0
  43. package/dist/cli/server/run-record.d.ts.map +1 -1
  44. package/dist/cli/server/run-record.js.map +1 -1
  45. package/dist/cli/server/sqlite-run-history-store.d.ts +6 -0
  46. package/dist/cli/server/sqlite-run-history-store.d.ts.map +1 -0
  47. package/dist/cli/server/sqlite-run-history-store.js +226 -0
  48. package/dist/cli/server/sqlite-run-history-store.js.map +1 -0
  49. package/dist/cli/server-app.d.ts +73 -2
  50. package/dist/cli/server-app.d.ts.map +1 -1
  51. package/dist/cli/server-app.js +409 -159
  52. package/dist/cli/server-app.js.map +1 -1
  53. package/dist/cli/session-title.js +1 -1
  54. package/dist/cli/sim-config.d.ts +13 -0
  55. package/dist/cli/sim-config.d.ts.map +1 -1
  56. package/dist/cli/sim-config.js +8 -1
  57. package/dist/cli/sim-config.js.map +1 -1
  58. package/dist/cli/simulate-route.d.ts +103 -0
  59. package/dist/cli/simulate-route.d.ts.map +1 -0
  60. package/dist/cli/simulate-route.js +95 -0
  61. package/dist/cli/simulate-route.js.map +1 -0
  62. package/dist/engine/compiler/cache.d.ts +2 -2
  63. package/dist/engine/compiler/cache.js +2 -2
  64. package/dist/engine/compiler/compile-from-seed.d.ts +78 -0
  65. package/dist/engine/compiler/compile-from-seed.d.ts.map +1 -0
  66. package/dist/engine/compiler/compile-from-seed.js +93 -0
  67. package/dist/engine/compiler/compile-from-seed.js.map +1 -0
  68. package/dist/engine/compiler/generate-fingerprint.d.ts.map +1 -1
  69. package/dist/engine/compiler/generate-fingerprint.js +3 -6
  70. package/dist/engine/compiler/generate-fingerprint.js.map +1 -1
  71. package/dist/engine/compiler/generate-politics.d.ts.map +1 -1
  72. package/dist/engine/compiler/generate-politics.js +3 -6
  73. package/dist/engine/compiler/generate-politics.js.map +1 -1
  74. package/dist/engine/compiler/generate-progression.d.ts +10 -1
  75. package/dist/engine/compiler/generate-progression.d.ts.map +1 -1
  76. package/dist/engine/compiler/generate-progression.js +15 -15
  77. package/dist/engine/compiler/generate-progression.js.map +1 -1
  78. package/dist/engine/compiler/generate-prompts.d.ts.map +1 -1
  79. package/dist/engine/compiler/generate-prompts.js +4 -7
  80. package/dist/engine/compiler/generate-prompts.js.map +1 -1
  81. package/dist/engine/compiler/generate-reactions.d.ts.map +1 -1
  82. package/dist/engine/compiler/generate-reactions.js +3 -6
  83. package/dist/engine/compiler/generate-reactions.js.map +1 -1
  84. package/dist/engine/compiler/index.d.ts +9 -6
  85. package/dist/engine/compiler/index.d.ts.map +1 -1
  86. package/dist/engine/compiler/index.js +9 -6
  87. package/dist/engine/compiler/index.js.map +1 -1
  88. package/dist/engine/compiler/sandbox-runner.d.ts +40 -0
  89. package/dist/engine/compiler/sandbox-runner.d.ts.map +1 -0
  90. package/dist/engine/compiler/sandbox-runner.js +278 -0
  91. package/dist/engine/compiler/sandbox-runner.js.map +1 -0
  92. package/dist/engine/compiler/scenario-fixture.d.ts +4 -4
  93. package/dist/engine/compiler/scenario-fixture.js +4 -4
  94. package/dist/engine/compiler/seed-ingestion.d.ts +2 -2
  95. package/dist/engine/compiler/seed-ingestion.js +2 -2
  96. package/dist/engine/compiler/state-shape-block.d.ts +1 -1
  97. package/dist/engine/compiler/state-shape-block.js +5 -5
  98. package/dist/engine/compiler/types.d.ts +2 -2
  99. package/dist/engine/compiler/types.d.ts.map +1 -1
  100. package/dist/engine/compiler/validate.js +1 -1
  101. package/dist/engine/core/kernel.d.ts +4 -4
  102. package/dist/engine/core/kernel.js +6 -6
  103. package/dist/engine/core/progression.d.ts +3 -3
  104. package/dist/engine/core/progression.js +21 -21
  105. package/dist/engine/core/state.d.ts +7 -5
  106. package/dist/engine/core/state.d.ts.map +1 -1
  107. package/dist/engine/digital-twin/index.d.ts +41 -0
  108. package/dist/engine/digital-twin/index.d.ts.map +1 -0
  109. package/dist/engine/digital-twin/index.js +40 -0
  110. package/dist/engine/digital-twin/index.js.map +1 -0
  111. package/dist/engine/index.d.ts +1 -1
  112. package/dist/engine/leader-presets.d.ts +39 -0
  113. package/dist/engine/leader-presets.d.ts.map +1 -0
  114. package/dist/engine/leader-presets.js +118 -0
  115. package/dist/engine/leader-presets.js.map +1 -0
  116. package/dist/engine/lunar/fingerprint.js +2 -2
  117. package/dist/engine/lunar/prompts.js +2 -2
  118. package/dist/engine/mars/fingerprint.js +1 -1
  119. package/dist/engine/mars/metrics.d.ts +2 -2
  120. package/dist/engine/mars/metrics.js +2 -2
  121. package/dist/engine/mars/prompts.js +3 -3
  122. package/dist/runtime/build-artifact.d.ts +2 -1
  123. package/dist/runtime/build-artifact.d.ts.map +1 -1
  124. package/dist/runtime/build-artifact.js +2 -1
  125. package/dist/runtime/build-artifact.js.map +1 -1
  126. package/dist/runtime/canonical-json.d.ts +25 -0
  127. package/dist/runtime/canonical-json.d.ts.map +1 -0
  128. package/dist/runtime/canonical-json.js +46 -0
  129. package/dist/runtime/canonical-json.js.map +1 -0
  130. package/dist/runtime/contracts.d.ts +1 -1
  131. package/dist/runtime/departments.js +1 -1
  132. package/dist/runtime/orchestrator.d.ts +44 -4
  133. package/dist/runtime/orchestrator.d.ts.map +1 -1
  134. package/dist/runtime/orchestrator.js +125 -33
  135. package/dist/runtime/orchestrator.js.map +1 -1
  136. package/dist/runtime/parsers.js +5 -5
  137. package/dist/runtime/reaction-step.js +2 -2
  138. package/dist/runtime/world-model/index.d.ts +172 -18
  139. package/dist/runtime/world-model/index.d.ts.map +1 -1
  140. package/dist/runtime/world-model/index.js +242 -4
  141. package/dist/runtime/world-model/index.js.map +1 -1
  142. package/dist/runtime/world-snapshot.d.ts +13 -0
  143. package/dist/runtime/world-snapshot.d.ts.map +1 -0
  144. package/dist/runtime/world-snapshot.js +19 -0
  145. package/dist/runtime/world-snapshot.js.map +1 -0
  146. package/package.json +19 -4
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  <h1 align="center">PARACOSM</h1>
6
6
 
7
7
  <p align="center">
8
- <em>The structured world model for AI agents. Reproducible counterfactual simulations from JSON.</em>
8
+ <em>From prompt to world model to forked futures. Structured counterfactual simulations for AI agents.</em>
9
9
  </p>
10
10
 
11
11
  <p align="center">
@@ -27,13 +27,15 @@
27
27
 
28
28
  ## What paracosm is
29
29
 
30
- A JSON file describes a world. A leader with a HEXACO personality profile runs it. A deterministic kernel drives state, time, and randomness. An LLM generates events, specialist analyses, and the leader's decisions. Specialists can forge new computational tools at runtime inside a V8 sandbox; an LLM judge approves each forge before it enters the decision pipeline. The kernel applies consequences. Personality traits drift. One turn ends, the next begins.
30
+ Paracosm starts from a prompt, brief, URL, or hand-written scenario draft; every path compiles down to an LLM-readable world contract before simulation. The durable contract is still JSON: a typed `ScenarioPackage` with five state bags, labels, departments, metrics, setup defaults, and generated hooks. A leader with a HEXACO personality profile runs that world. A deterministic kernel drives state, time, and randomness. An LLM generates events, specialist analyses, and the leader's decisions. Specialists can forge new computational tools at runtime inside a V8 sandbox; an LLM judge approves each forge before it enters the decision pipeline. The kernel applies consequences. Personality traits drift. One turn ends, the next begins.
31
+
32
+ **JSON is the contract, not the product boundary.** Today, `compileScenario()` accepts a scenario JSON draft and can ground it with `seedText` or `seedUrl`. The next API layer should be a one-call prompt/document wrapper that asks an LLM to propose that same JSON contract, validates it, then compiles and runs it. It should not bypass the schema, the kernel, or the artifact.
31
33
 
32
34
  **Same seed. Different leader. Different world.**
33
35
 
34
- Two runs against an identical seed, starting from the same JSON, produce measurably divergent trajectories when you swap one variable: the leader's personality. The kernel's side is reproducible. The divergence comes from the LLM stages reading HEXACO profiles and deciding differently. That structural contrast is the product.
36
+ Two runs against an identical seed, starting from the same compiled world contract, produce measurably divergent trajectories when you swap one variable: the leader's personality. The kernel's side is reproducible. The divergence comes from the LLM stages reading HEXACO profiles and deciding differently. That structural contrast is the product.
35
37
 
36
- Paracosm is a **structured world model** in the sense of [Xing 2025](https://arxiv.org/abs/2507.05169) and the [ACM CSUR 2025 world-model survey](https://dl.acm.org/doi/full/10.1145/3746449): a simulator for *actionable possibilities*, not a video generator. It is also a **counterfactual world simulation model** ([Kirfel et al, 2025](https://link.springer.com/article/10.1007/s43681-025-00718-4)): a substrate for replaying an event with one variable changed and surfacing the effect. Full taxonomy mapping in [`docs/positioning/world-model-mapping.md`](docs/positioning/world-model-mapping.md).
38
+ Paracosm is a **structured world model** in the sense of [Xing 2025](https://arxiv.org/abs/2507.05169) and the [ACM CSUR 2025 world-model survey](https://dl.acm.org/doi/full/10.1145/3746449): a simulator for *actionable possibilities*, not a video generator. It is also a **counterfactual world simulation model** ([Kirfel et al, 2025](https://link.springer.com/article/10.1007/s43681-025-00718-4)): a substrate for replaying an event with one variable changed and surfacing the effect. The closest LLM-world-model implementation anchor is [Yang et al, 2026](https://openreview.net/forum?id=XmYCERErcD), which evaluates LLM-based world models through policy verification, action proposal, and policy planning. Paracosm takes the safe product version of that idea: externalize the world into schema, citations, tools, snapshots, and seeded transitions, then let the LLM reason over that structure. Full taxonomy mapping in [`docs/positioning/world-model-mapping.md`](docs/positioning/world-model-mapping.md).
37
39
 
38
40
  ### Not these things
39
41
 
@@ -47,7 +49,7 @@ Leaders can be colony commanders, CEOs, generals, ship captains, department head
47
49
 
48
50
  ### Counterfactual simulations with `WorldModel.fork()`
49
51
 
50
- The CWSM positioning is operationalized through `WorldModel.fork()`: run a simulation with snapshots enabled, then branch at any past turn with a different leader or seed, and compare.
52
+ The CWSM positioning is operationalized through `WorldModel.fork()`: run a simulation with snapshots enabled, then branch at any past turn with a different leader or seed, and compare. On resumed runs, `maxTurns` remains the absolute final turn index. To run three additional turns from turn 3, pass `maxTurns: 6`.
51
53
 
52
54
  ```typescript
53
55
  import { WorldModel } from 'paracosm/world-model';
@@ -64,7 +66,7 @@ const trunk = await wm.simulate(visionaryLeader, {
64
66
  // the forked kernel resumes from the captured state.
65
67
  const branch = await (await wm.forkFromArtifact(trunk, 3)).simulate(
66
68
  pragmatistLeader,
67
- { maxTurns: 3, seed: 42 },
69
+ { maxTurns: 6, seed: 42 },
68
70
  );
69
71
 
70
72
  console.log(trunk.metadata.runId); // parent run-id
@@ -74,7 +76,48 @@ console.log(trunk.fingerprint, branch.fingerprint); // divergent futures from th
74
76
 
75
77
  The kernel round-trips through `JSON.stringify`, so snapshots persist to disk cleanly for later replay or audit. `captureSnapshots` defaults to `false` to keep normal artifacts lean; set it when you want fork capability.
76
78
 
77
- ## Quickstart
79
+ The paracosm dashboard exposes the same mechanism end-to-end. Every UI-initiated run captures snapshots by default, so the Reports tab shows a `↳ Fork at {Time} N` button on each completed turn. Clicking it opens a fork modal (leader override, optional seed, optional custom events), POSTs to `/setup` with the full parent artifact, and routes the user to a new **Branches** tab where all forks launched from the current parent accumulate as cards with per-metric deltas rendered live as each branch streams to completion.
80
+
81
+ ### Replay any run for audit
82
+
83
+ ```typescript
84
+ const replay = await wm.replay(storedArtifact);
85
+ console.log(replay.matches); // true when the kernel produces byte-equal output
86
+ console.log(replay.divergence); // first-mismatch JSON pointer when matches=false
87
+ ```
88
+
89
+ The kernel's between-turn progression hook re-runs deterministically from each recorded snapshot; LLM stages are not invoked, so replay is free and fast. Use it for regression testing (replay golden artifacts in CI) or forensic comparison (find the first kernel-state divergence between two versions of paracosm). Pillar 2 (Reproducible) becomes verifiable in code rather than promised in copy.
90
+
91
+ ### Subpath for digital-twin use cases
92
+
93
+ ```typescript
94
+ import { DigitalTwin, type SubjectConfig, type InterventionConfig } from 'paracosm/digital-twin';
95
+
96
+ const twin = await DigitalTwin.fromJson(scenarioJson);
97
+ const artifact = await twin.simulateIntervention(subject, intervention, leader);
98
+ ```
99
+
100
+ `DigitalTwin` is an alias of `WorldModel`; the subpath names the use case in the import path. The new `simulateIntervention()` sugar populates `RunArtifact.subject` and `RunArtifact.intervention` for traceability.
101
+
102
+ ### Quickstart: prompt or document to running simulation
103
+
104
+ `WorldModel.fromPrompt` compiles a scenario from seed source material (paste, URL, or extracted PDF text), then `wm.quickstart` generates N contextual HEXACO leaders and runs them in parallel. Every prompt/document path validates against `DraftScenarioSchema` and routes into the existing `compileScenario` pipeline: the canonical `ScenarioPackage` contract is never bypassed.
105
+
106
+ ```typescript
107
+ import { WorldModel } from 'paracosm/world-model';
108
+
109
+ const wm = await WorldModel.fromPrompt({
110
+ seedText: 'Q3 board brief: the company must decide between...',
111
+ domainHint: 'corporate strategic decision',
112
+ });
113
+
114
+ const { leaders, artifacts } = await wm.quickstart({ leaderCount: 3 });
115
+ artifacts.forEach((a, i) => console.log(leaders[i].name, a.fingerprint));
116
+ ```
117
+
118
+ In the dashboard, the Quickstart tab is the default landing view. A user pastes a brief (or drops a PDF, or supplies a URL) and receives three streaming-live leaders plus per-card Download JSON, Copy shareable link, and Fork-in-Branches actions within a minute of first click. A curated library of 10 HEXACO archetypes is exported at `paracosm/leader-presets` for programmatic `runBatch` sweeps or Swap-leader controls in downstream UIs.
119
+
120
+ ## Install
78
121
 
79
122
  ```bash
80
123
  npm install paracosm # also works: pnpm add paracosm / bun add paracosm
@@ -84,6 +127,8 @@ Paracosm ships as pure ESM with subpath exports (`paracosm/compiler`, `paracosm/
84
127
 
85
128
  ### 1. Define your world
86
129
 
130
+ The canonical authoring contract is JSON because JSON can be validated, diffed, cached, snapshotted, and exported as schema. You can write that draft directly, or ground it with natural-language source material through `seedText` / `seedUrl` during compilation. A future prompt-only wrapper should generate this same contract first, then compile it.
131
+
87
132
  Every scenario declares its own vocabulary via `labels.populationNoun`
88
133
  (plural, e.g. `"colonists"` / `"crew"` / `"citizens"`) and
89
134
  `labels.settlementNoun` (singular, e.g. `"colony"` / `"habitat"` /
@@ -164,7 +209,7 @@ import { compileScenario } from 'paracosm/compiler';
164
209
  import { runSimulation } from 'paracosm/runtime';
165
210
  import worldJson from './my-world.json' with { type: 'json' };
166
211
 
167
- // Compile JSON into a runnable scenario (~$0.10, cached to disk)
212
+ // Compile a typed world draft into a runnable scenario (~$0.10, cached to disk)
168
213
  const scenario = await compileScenario(worldJson, {
169
214
  provider: 'anthropic',
170
215
  model: 'claude-sonnet-4-6',
@@ -333,7 +378,7 @@ Then edit the HEXACO sliders and `instructions` fields to describe your own lead
333
378
 
334
379
  ## Scenario Compiler
335
380
 
336
- The compiler turns your JSON into a runnable scenario by generating TypeScript hooks via LLM calls:
381
+ The compiler turns a typed world draft plus optional prompt/document/URL grounding into a runnable scenario by generating TypeScript hooks via LLM calls:
337
382
 
338
383
  ```bash
339
384
  npm run compile -- scenarios/submarine.json \
@@ -341,7 +386,7 @@ npm run compile -- scenarios/submarine.json \
341
386
  --no-web-search
342
387
  ```
343
388
 
344
- Options: `--seed-text`, `--seed-url`, `--no-web-search`, `--max-searches`. Compiled scenarios appear in the dashboard selector. Cost is roughly $0.10 per compile, cached to disk after first generation.
389
+ Options: `--seed-text`, `--seed-url`, `--no-web-search`, `--max-searches`. Use `--seed-text` for a pasted brief or prompt, and `--seed-url` for a report, paper, or web page. The JSON file remains the contract that gets validated and cached; seed material grounds the world before hook generation. Compiled scenarios appear in the dashboard selector. Cost is roughly $0.10 per compile, cached to disk after first generation.
345
390
 
346
391
  ### Programmatic compiler options
347
392
 
@@ -400,6 +445,26 @@ The orchestrator's `runSimulation()` returns a `cost` field with token counts, L
400
445
 
401
446
  Every LLM call site on both providers routes its stable system prefix through a `cacheBreakpoint: true` block (director instructions, department prompts, reaction batches, compile-time hook generators). On Anthropic, turn 2+ of every run serves the shared prefix from the provider's prompt cache at 0.1× input cost. On OpenAI, any prompt ≥ 1024 tokens auto-caches. The `cost.caches` field reports read / creation tokens and USD saved per run, and `/retry-stats` rolls the numbers up across the last 100 runs so you can verify the cache is actually hitting. No configuration required. The `system: Array<{ text; cacheBreakpoint }>` shape is built into the validated-call wrappers in `src/engine/compiler/llm-invocations/` and `src/runtime/llm-invocations/`.
402
447
 
448
+ ## One-shot HTTP API: `POST /simulate`
449
+
450
+ Non-SSE consumers (curl, Python integrations, third-party dashboards) can run a simulation through a plain request-response endpoint. Gated behind `PARACOSM_ENABLE_SIMULATE_ENDPOINT=true` so the hosted demo's SSE-first path stays the default; self-hosted deployments flip the flag on.
451
+
452
+ ```bash
453
+ export PARACOSM_ENABLE_SIMULATE_ENDPOINT=true
454
+ npx paracosm serve # or bring up your own server via createMarsServer
455
+
456
+ curl -s -X POST http://localhost:5188/simulate \
457
+ -H 'Content-Type: application/json' \
458
+ -H 'X-Anthropic-Key: sk-ant-...' \
459
+ -d '{
460
+ "scenario": { "id": "submarine-habitat", "labels": { "name": "Deep Ocean Habitat", "populationNoun": "crew", "settlementNoun": "habitat", "timeUnitNoun": "day" }, "setup": { "defaultTurns": 4, "defaultPopulation": 25, "defaultStartTime": 2040 }, "departments": [...], "metrics": [...] },
461
+ "leader": { "name": "Captain Reyes", "archetype": "The Pragmatist", "unit": "Deep Ocean Habitat", "hexaco": { "openness": 0.4, "conscientiousness": 0.9, "extraversion": 0.3, "agreeableness": 0.6, "emotionality": 0.5, "honestyHumility": 0.8 }, "instructions": "" },
462
+ "options": { "maxTurns": 4, "seed": 42, "captureSnapshots": true, "provider": "anthropic" }
463
+ }' | jq '.artifact.fingerprint'
464
+ ```
465
+
466
+ The request body accepts either a pre-compiled `ScenarioPackage` (has `.hooks`) or a raw scenario draft the compiler accepts; raw drafts are auto-compiled server-side with optional `options.seedText` / `options.seedUrl` grounding. The response body is `{ artifact: RunArtifact, scenario: ScenarioPackage, durationMs: number }`. Rate limiting shares the same IP bucket as `/setup`; request-body size uses the same 5 MiB cap.
467
+
403
468
  ## Programmatic API
404
469
 
405
470
  Everything the dashboard does is also available as library calls. The exports fall into five buckets:
@@ -693,7 +758,7 @@ Each turn represents a configurable time period. Mars and Lunar tick in years (M
693
758
  3. DEPARTMENT ANALYSIS All active departments analyze the event in parallel.
694
759
  Each department head (promoted at turn 0) uses their
695
760
  personality and tools. Departments can forge new
696
- computational tools at runtime (sandboxed V8, LLM-judged).
761
+ computational tools at runtime (hardened node:vm, LLM-judged).
697
762
 
698
763
  4. COMMANDER DECISION Reads all department reports. Selects an option.
699
764
  Personality shapes risk tolerance and priority weighting.
@@ -729,7 +794,7 @@ Department heads are LLM agents with domain-specific instructions, access to res
729
794
 
730
795
  - Analyze the event against their department's research knowledge
731
796
  - Cite relevant scientific literature (DOI-linked)
732
- - Forge computational tools (e.g., a radiation dose calculator) in a sandboxed V8 environment
797
+ - Forge computational tools (e.g., a radiation dose calculator) in a hardened node:vm sandbox
733
798
  - An LLM judge reviews each tool for safety and correctness
734
799
  - Produce a structured report: summary, risks, recommended actions, proposed colony state changes
735
800
 
@@ -741,7 +806,7 @@ The commander sees all department reports and makes a decision. Different comman
741
806
  src/
742
807
  engine/ the npm package
743
808
  core/ deterministic kernel (RNG, state, progression, personality drift)
744
- compiler/ JSON -> ScenarioPackage compiler
809
+ compiler/ scenario draft + source grounding -> ScenarioPackage compiler
745
810
  mars/ Mars Genesis scenario
746
811
  lunar/ Lunar Outpost scenario
747
812
 
@@ -782,7 +847,7 @@ Paracosm uses [AgentOS](https://agentos.sh) for agent orchestration, LLM calls,
782
847
  |------------|----------|
783
848
  | `agent()` | Commander, department, and Event Director agents |
784
849
  | `generateText()` | LLM calls for event generation and tool evaluation |
785
- | `EmergentCapabilityEngine` | Runtime tool forging in sandboxed V8 |
850
+ | `EmergentCapabilityEngine` | Runtime tool forging in a hardened node:vm sandbox |
786
851
  | `EmergentJudge` | LLM-as-judge safety review of forged tools |
787
852
 
788
853
  ## Links
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * CLI: Compile a scenario JSON into a runnable ScenarioPackage.
3
+ * CLI: Compile a scenario JSON draft into a runnable ScenarioPackage.
4
4
  *
5
5
  * Usage:
6
6
  * npx tsx src/cli/compile.ts scenarios/submarine.json
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * CLI: Compile a scenario JSON into a runnable ScenarioPackage.
3
+ * CLI: Compile a scenario JSON draft into a runnable ScenarioPackage.
4
4
  *
5
5
  * Usage:
6
6
  * npx tsx src/cli/compile.ts scenarios/submarine.json
@@ -16,7 +16,7 @@ async function main() {
16
16
  const options = parseCompileCliOptions(rawArgs);
17
17
  if (rawArgs.length === 0 || rawArgs.includes('--help') || rawArgs.includes('-h')) {
18
18
  console.log(`
19
- paracosm compile Generate runtime hooks for a scenario JSON
19
+ paracosm compile - Generate runtime hooks for a scenario JSON draft
20
20
 
21
21
  Usage:
22
22
  npx tsx src/cli/compile.ts <scenario.json> [options]
@@ -26,8 +26,8 @@ Options:
26
26
  --model <model> Model name (default: claude-sonnet-4-6)
27
27
  --no-cache Skip disk cache
28
28
  --cache-dir <dir> Cache directory (default: .paracosm/cache)
29
- --seed-text <text> Seed scenario knowledge from inline text before hook generation
30
- --seed-url <url> Seed scenario knowledge from a URL before hook generation
29
+ --seed-text <text> Ground the scenario with an inline prompt, brief, or document
30
+ --seed-url <url> Ground the scenario with a URL before hook generation
31
31
  --no-web-search Skip live citation grounding during seed ingestion
32
32
  --max-searches <n> Cap the number of live grounding searches during seed ingestion
33
33
  -h, --help Show this help
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Shared URL fetcher for CLI init + dashboard quickstart flows.
3
+ *
4
+ * AgentOS exposes WebSearchService from the `@framers/agentos/web-search`
5
+ * subpath. The package root does not export it, and the service is a
6
+ * search API rather than a single-URL scraper. This helper uses the real
7
+ * search API when provider keys are configured, then falls back to direct
8
+ * text/HTML fetch for ordinary public URLs.
9
+ *
10
+ * @module paracosm/cli/fetch-seed-url
11
+ */
12
+ export interface FetchedSeedUrl {
13
+ text: string;
14
+ title: string;
15
+ sourceUrl: string;
16
+ }
17
+ export interface WebSearchResultLike {
18
+ url: string;
19
+ title: string;
20
+ snippet: string;
21
+ content?: string;
22
+ }
23
+ export interface WebSearchClient {
24
+ registerProvider: (provider: any) => void;
25
+ hasProviders: () => boolean;
26
+ search: (query: string, options?: {
27
+ maxResults?: number;
28
+ rerank?: boolean;
29
+ }) => Promise<WebSearchResultLike[]>;
30
+ }
31
+ export type WebSearchServiceCtor = new (opts?: any) => WebSearchClient;
32
+ export type WebSearchProviderCtor = new (apiKey: string) => unknown;
33
+ export interface WebSearchModule {
34
+ WebSearchService: WebSearchServiceCtor;
35
+ FirecrawlProvider: WebSearchProviderCtor;
36
+ TavilyProvider: WebSearchProviderCtor;
37
+ SerperProvider: WebSearchProviderCtor;
38
+ BraveProvider: WebSearchProviderCtor;
39
+ }
40
+ export type WebSearchImporter = () => Promise<WebSearchModule>;
41
+ export interface FetchSeedFromUrlOptions {
42
+ importWebSearch?: WebSearchImporter;
43
+ env?: NodeJS.ProcessEnv | Record<string, string | undefined>;
44
+ fetchImpl?: typeof fetch;
45
+ }
46
+ export declare function loadWebSearchModule(importWebSearch?: WebSearchImporter): Promise<WebSearchModule>;
47
+ export declare function fetchSeedFromUrl(url: string, options?: FetchSeedFromUrlOptions): Promise<FetchedSeedUrl>;
48
+ //# sourceMappingURL=fetch-seed-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-seed-url.d.ts","sourceRoot":"","sources":["../../src/cli/fetch-seed-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B,MAAM,EAAE,CACN,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAChD,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;CACrC;AAED,MAAM,MAAM,oBAAoB,GAAG,KAAK,IAAI,CAAC,EAAE,GAAG,KAAK,eAAe,CAAC;AACvE,MAAM,MAAM,qBAAqB,GAAG,KAAK,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,oBAAoB,CAAC;IACvC,iBAAiB,EAAE,qBAAqB,CAAC;IACzC,cAAc,EAAE,qBAAqB,CAAC;IACtC,cAAc,EAAE,qBAAqB,CAAC;IACtC,aAAa,EAAE,qBAAqB,CAAC;CACtC;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;AAE/D,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,iBAAiB,CAAC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,wBAAsB,mBAAmB,CACvC,eAAe,GAAE,iBAA+D,GAC/E,OAAO,CAAC,eAAe,CAAC,CAE1B;AAiGD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,cAAc,CAAC,CASzB"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Shared URL fetcher for CLI init + dashboard quickstart flows.
3
+ *
4
+ * AgentOS exposes WebSearchService from the `@framers/agentos/web-search`
5
+ * subpath. The package root does not export it, and the service is a
6
+ * search API rather than a single-URL scraper. This helper uses the real
7
+ * search API when provider keys are configured, then falls back to direct
8
+ * text/HTML fetch for ordinary public URLs.
9
+ *
10
+ * @module paracosm/cli/fetch-seed-url
11
+ */
12
+ export async function loadWebSearchModule(importWebSearch = () => import('@framers/agentos/web-search')) {
13
+ return importWebSearch();
14
+ }
15
+ function registerConfiguredProviders(service, mod, env) {
16
+ if (env.FIRECRAWL_API_KEY)
17
+ service.registerProvider(new mod.FirecrawlProvider(env.FIRECRAWL_API_KEY));
18
+ if (env.TAVILY_API_KEY)
19
+ service.registerProvider(new mod.TavilyProvider(env.TAVILY_API_KEY));
20
+ if (env.SERPER_API_KEY)
21
+ service.registerProvider(new mod.SerperProvider(env.SERPER_API_KEY));
22
+ if (env.BRAVE_API_KEY)
23
+ service.registerProvider(new mod.BraveProvider(env.BRAVE_API_KEY));
24
+ }
25
+ function normalizeUrlForCompare(raw) {
26
+ try {
27
+ const url = new URL(raw);
28
+ url.hash = '';
29
+ return url.toString().replace(/\/$/, '');
30
+ }
31
+ catch {
32
+ return raw.replace(/\/$/, '');
33
+ }
34
+ }
35
+ async function fetchViaAgentOSSearch(url, options) {
36
+ const mod = await loadWebSearchModule(options.importWebSearch);
37
+ const service = new mod.WebSearchService({ maxResults: 5 });
38
+ registerConfiguredProviders(service, mod, options.env ?? process.env);
39
+ if (!service.hasProviders())
40
+ return null;
41
+ const results = await service.search(url, { maxResults: 5, rerank: false });
42
+ if (results.length === 0)
43
+ return null;
44
+ const wanted = normalizeUrlForCompare(url);
45
+ const exact = results.find((result) => normalizeUrlForCompare(result.url) === wanted);
46
+ const withContent = results.find((result) => typeof result.content === 'string' && result.content.trim().length > 0);
47
+ const result = exact ?? withContent ?? results[0];
48
+ const text = (result.content || result.snippet || '').trim();
49
+ if (!text)
50
+ return null;
51
+ return {
52
+ text,
53
+ title: result.title || '',
54
+ sourceUrl: url,
55
+ };
56
+ }
57
+ function decodeBasicHtmlEntities(text) {
58
+ return text
59
+ .replace(/&nbsp;/g, ' ')
60
+ .replace(/&amp;/g, '&')
61
+ .replace(/&lt;/g, '<')
62
+ .replace(/&gt;/g, '>')
63
+ .replace(/&quot;/g, '"')
64
+ .replace(/&#39;/g, "'");
65
+ }
66
+ function extractTitleFromHtml(html) {
67
+ const match = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
68
+ return match ? decodeBasicHtmlEntities(match[1].replace(/\s+/g, ' ').trim()) : '';
69
+ }
70
+ function stripHtmlToText(html) {
71
+ return decodeBasicHtmlEntities(html
72
+ .replace(/<head[\s\S]*?<\/head>/gi, ' ')
73
+ .replace(/<script[\s\S]*?<\/script>/gi, ' ')
74
+ .replace(/<style[\s\S]*?<\/style>/gi, ' ')
75
+ .replace(/<noscript[\s\S]*?<\/noscript>/gi, ' ')
76
+ .replace(/<[^>]+>/g, ' ')
77
+ .replace(/\s+/g, ' ')
78
+ .trim());
79
+ }
80
+ async function fetchDirectly(url, fetchImpl = fetch) {
81
+ const res = await fetchImpl(url, {
82
+ headers: { Accept: 'text/html,text/plain,application/xhtml+xml;q=0.9,*/*;q=0.1' },
83
+ signal: AbortSignal.timeout(15_000),
84
+ });
85
+ if (!res.ok) {
86
+ throw new Error(`HTTP ${res.status}`);
87
+ }
88
+ const contentType = res.headers.get('content-type') || '';
89
+ const raw = await res.text();
90
+ const isHtml = /\bhtml\b/i.test(contentType) || /<html[\s>]/i.test(raw);
91
+ return {
92
+ text: isHtml ? stripHtmlToText(raw) : raw.trim(),
93
+ title: isHtml ? extractTitleFromHtml(raw) : '',
94
+ sourceUrl: url,
95
+ };
96
+ }
97
+ export async function fetchSeedFromUrl(url, options = {}) {
98
+ try {
99
+ const viaSearch = await fetchViaAgentOSSearch(url, options);
100
+ if (viaSearch)
101
+ return viaSearch;
102
+ }
103
+ catch {
104
+ // Fall through to direct fetch. Some AgentOS providers are search-only
105
+ // and may reject exact URL lookups; public URLs can still be fetched.
106
+ }
107
+ return fetchDirectly(url, options.fetchImpl);
108
+ }
109
+ //# sourceMappingURL=fetch-seed-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-seed-url.js","sourceRoot":"","sources":["../../src/cli/fetch-seed-url.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type RunArtifact } from '../engine/schema/index.js';
2
+ export type ForkPreconditionResult = {
3
+ ok: true;
4
+ parentArtifact: RunArtifact;
5
+ } | {
6
+ ok: false;
7
+ statusCode: 400 | 409;
8
+ error: string;
9
+ issues?: string[];
10
+ };
11
+ export declare function validateForkSetupPreconditions(input: {
12
+ parentArtifact: unknown;
13
+ atTurn: number;
14
+ activeScenarioId: string;
15
+ activeRunInProgress: boolean;
16
+ }): ForkPreconditionResult;
17
+ //# sourceMappingURL=fork-preconditions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fork-preconditions.d.ts","sourceRoot":"","sources":["../../src/cli/fork-preconditions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAEhF,MAAM,MAAM,sBAAsB,GAC9B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,cAAc,EAAE,WAAW,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE3E,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;CAC9B,GAAG,sBAAsB,CAoDzB"}
@@ -0,0 +1,51 @@
1
+ import { RunArtifactSchema } from '../engine/schema/index.js';
2
+ export function validateForkSetupPreconditions(input) {
3
+ const parentResult = RunArtifactSchema.safeParse(input.parentArtifact);
4
+ if (!parentResult.success) {
5
+ return {
6
+ ok: false,
7
+ statusCode: 400,
8
+ error: 'Fork parent artifact is not a valid RunArtifact.',
9
+ issues: parentResult.error.issues.slice(0, 5).map(issue => issue.message),
10
+ };
11
+ }
12
+ const parent = parentResult.data;
13
+ const parentScenarioId = parent.metadata.scenario.id;
14
+ if (parentScenarioId !== input.activeScenarioId) {
15
+ return {
16
+ ok: false,
17
+ statusCode: 400,
18
+ error: `Fork parent scenario '${parentScenarioId}' does not match active scenario '${input.activeScenarioId}'. Cross-scenario forks are not supported.`,
19
+ };
20
+ }
21
+ const snapshots = parent.scenarioExtensions
22
+ ?.kernelSnapshotsPerTurn;
23
+ if (!Array.isArray(snapshots) || snapshots.length === 0) {
24
+ return {
25
+ ok: false,
26
+ statusCode: 400,
27
+ error: 'Fork parent has no embedded kernel snapshots. Re-run the parent simulation with `captureSnapshots: true` to enable forking.',
28
+ };
29
+ }
30
+ const hasRequestedSnapshot = snapshots.some(snapshot => {
31
+ if (!snapshot || typeof snapshot !== 'object')
32
+ return false;
33
+ return snapshot.turn === input.atTurn;
34
+ });
35
+ if (!hasRequestedSnapshot) {
36
+ return {
37
+ ok: false,
38
+ statusCode: 400,
39
+ error: `Fork parent has no kernel snapshot for turn ${input.atTurn}.`,
40
+ };
41
+ }
42
+ if (input.activeRunInProgress) {
43
+ return {
44
+ ok: false,
45
+ statusCode: 409,
46
+ error: 'Cannot fork while another simulation is running. Wait for the current run to finish or stop it first.',
47
+ };
48
+ }
49
+ return { ok: true, parentArtifact: parent };
50
+ }
51
+ //# sourceMappingURL=fork-preconditions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fork-preconditions.js","sourceRoot":"","sources":["../../src/cli/fork-preconditions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,2BAA2B,CAAC;AAMhF,MAAM,UAAU,8BAA8B,CAAC,KAK9C;IACC,MAAM,YAAY,GAAG,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACvE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,kDAAkD;YACzD,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;SAC1E,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC;IACjC,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;IACrD,IAAI,gBAAgB,KAAK,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAChD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,yBAAyB,gBAAgB,qCAAqC,KAAK,CAAC,gBAAgB,4CAA4C;SACxJ,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAI,MAAM,CAAC,kBAAyE;QACjG,EAAE,sBAAsB,CAAC;IAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,6HAA6H;SACrI,CAAC;IACJ,CAAC;IAED,MAAM,oBAAoB,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACrD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5D,OAAQ,QAA+B,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC;IAChE,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,+CAA+C,KAAK,CAAC,MAAM,GAAG;SACtE,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC9B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,UAAU,EAAE,GAAG;YACf,KAAK,EAAE,uGAAuG;SAC/G,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Pure renderer functions for the files emitted by `paracosm init`.
3
+ * Each function takes a small input record and returns the file contents
4
+ * as a string. No I/O, no dependencies on the caller's environment.
5
+ *
6
+ * Kept separate from init.ts so the renderers snapshot-test trivially.
7
+ *
8
+ * @module paracosm/cli/init-templates
9
+ */
10
+ export interface PackageJsonInput {
11
+ name: string;
12
+ paracosmVersion: string;
13
+ }
14
+ export declare function renderPackageJson(input: PackageJsonInput): string;
15
+ export type SimulationMode = 'turn-loop' | 'batch-trajectory' | 'batch-point';
16
+ /**
17
+ * Render the entry script for a paracosm-init scaffolded project.
18
+ *
19
+ * The script imports `runSimulation` from `paracosm/runtime` and runs the
20
+ * leader at index 0 against a turn-loop simulation. Mode is intentionally
21
+ * NOT a runtime input: it is a property of the produced
22
+ * `RunArtifact.metadata`, surfaced after the run completes. Batch-trajectory
23
+ * and batch-point modes are produced by `runBatch` (different entry point,
24
+ * different config shape); a future spec adds a separate `renderRunMjsBatch`
25
+ * for those modes.
26
+ */
27
+ export declare function renderRunMjs(): string;
28
+ export interface ReadmeInput {
29
+ name: string;
30
+ domain: string;
31
+ mode: SimulationMode;
32
+ leaders: number;
33
+ }
34
+ export declare function renderReadme(input: ReadmeInput): string;
35
+ export declare function renderEnvExample(): string;
36
+ export declare function renderGitignore(): string;
37
+ /**
38
+ * Slug-normalize a project name. Lowercase ASCII, dashes between words,
39
+ * strips everything else, max 50 chars. If empty after stripping,
40
+ * returns 'paracosm-app'.
41
+ */
42
+ export declare function slugifyName(raw: string): string;
43
+ //# sourceMappingURL=init-templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-templates.d.ts","sourceRoot":"","sources":["../../src/cli/init-templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAcjE;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,kBAAkB,GAAG,aAAa,CAAC;AAE9E;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAqCrC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA8BvD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAWzC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAQxC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS/C"}