substrate-ai 0.19.51 → 0.19.53
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/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createLogger } from "../logger-KeHncl-f.js";
|
|
|
4
4
|
import { createEventBus } from "../helpers-CElYrONe.js";
|
|
5
5
|
import { AdapterRegistry, BudgetConfigSchema, CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, ConfigError, CostTrackerConfigSchema, DEFAULT_CONFIG, DoltClient, DoltNotInstalled, GlobalSettingsSchema, IngestionServer, MonitorDatabaseImpl, OPERATIONAL_FINDING, PartialGlobalSettingsSchema, PartialProviderConfigSchema, ProvidersSchema, RoutingRecommender, STORY_METRICS, TelemetryConfigSchema, addTokenUsage, aggregateTokenUsageForRun, checkDoltInstalled, compareRunMetrics, createAmendmentRun, createConfigSystem, createDecision, createDoltClient, createPipelineRun, getActiveDecisions, getAllCostEntriesFiltered, getBaselineRunMetrics, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestCompletedRun, getLatestRun, getPipelineRunById, getPlanningCostTotal, getRetryableEscalations, getRunMetrics, getRunningPipelineRuns, getSessionCostSummary, getSessionCostSummaryFiltered, getStoryMetricsForRun, getTokenUsageSummary, incrementRunRestarts, initSchema, initializeDolt, listRunMetrics, loadParentRunDecisions, supersedeDecision, tagRunAsBaseline, updatePipelineRun } from "../dist-sNh9XQ6V.js";
|
|
6
6
|
import "../adapter-registry-DXLMTmfD.js";
|
|
7
|
-
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-
|
|
7
|
+
import { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-BUKozIHS.js";
|
|
8
8
|
import "../errors-RupuC-ES.js";
|
|
9
9
|
import "../routing-CcBOCuC9.js";
|
|
10
10
|
import "../decisions-C0pz9Clx.js";
|
|
@@ -2284,6 +2284,164 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
|
|
|
2284
2284
|
logger$15.warn({ err }, "scaffoldClaudeCommands failed; init continues");
|
|
2285
2285
|
}
|
|
2286
2286
|
}
|
|
2287
|
+
/**
|
|
2288
|
+
* Sync every `.md` file from a source commands directory into a target prompts
|
|
2289
|
+
* directory, flat. Codex CLI loads `<root>/.codex/prompts/*.md` as slash
|
|
2290
|
+
* commands, so the already-generated Claude command files map 1:1.
|
|
2291
|
+
*
|
|
2292
|
+
* On re-runs, any `.md` file in the target that matches `ownershipPrefixes`
|
|
2293
|
+
* but is no longer present in the source is removed, so stale substrate-
|
|
2294
|
+
* generated prompts don't accumulate. `.md` files without a matching prefix
|
|
2295
|
+
* are left untouched (protecting user-authored content in `~/.codex/`).
|
|
2296
|
+
*
|
|
2297
|
+
* Returns the number of prompt files written.
|
|
2298
|
+
*/
|
|
2299
|
+
function syncCommandsAsPrompts(commandsDir, promptsDir, ownershipPrefixes, namePrefix) {
|
|
2300
|
+
if (!existsSync$1(commandsDir)) return 0;
|
|
2301
|
+
mkdirSync$1(promptsDir, { recursive: true });
|
|
2302
|
+
const sourceEntries = readdirSync$1(commandsDir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".md"));
|
|
2303
|
+
const destNames = new Set(sourceEntries.map((e) => namePrefix && !e.name.startsWith(namePrefix) ? `${namePrefix}${e.name}` : e.name));
|
|
2304
|
+
try {
|
|
2305
|
+
for (const entry of readdirSync$1(promptsDir, { withFileTypes: true })) {
|
|
2306
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
2307
|
+
const isOwned = ownershipPrefixes.some((p) => entry.name.startsWith(p));
|
|
2308
|
+
if (!isOwned) continue;
|
|
2309
|
+
if (destNames.has(entry.name)) continue;
|
|
2310
|
+
unlinkSync$1(join(promptsDir, entry.name));
|
|
2311
|
+
}
|
|
2312
|
+
} catch (err) {
|
|
2313
|
+
logger$15.debug({
|
|
2314
|
+
err,
|
|
2315
|
+
promptsDir
|
|
2316
|
+
}, "Failed to prune stale prompts");
|
|
2317
|
+
}
|
|
2318
|
+
let count = 0;
|
|
2319
|
+
for (const entry of sourceEntries) {
|
|
2320
|
+
const destName = namePrefix && !entry.name.startsWith(namePrefix) ? `${namePrefix}${entry.name}` : entry.name;
|
|
2321
|
+
cpSync(join(commandsDir, entry.name), join(promptsDir, destName));
|
|
2322
|
+
count++;
|
|
2323
|
+
}
|
|
2324
|
+
return count;
|
|
2325
|
+
}
|
|
2326
|
+
/**
|
|
2327
|
+
* Sync skill directories from a source skills root into a target skills root,
|
|
2328
|
+
* optionally namespaced under `namePrefix`.
|
|
2329
|
+
*
|
|
2330
|
+
* Every direct child directory of `srcSkillsDir` is treated as a skill bundle
|
|
2331
|
+
* (no SKILL.md check — the source is always `.claude/skills/` which has
|
|
2332
|
+
* already been sanitized by `prepareSkillsDir`). On re-runs, any skill
|
|
2333
|
+
* directory in the target whose name starts with one of `ownershipPrefixes`
|
|
2334
|
+
* but is no longer present in the source is removed.
|
|
2335
|
+
*
|
|
2336
|
+
* Returns the number of skill directories copied.
|
|
2337
|
+
*/
|
|
2338
|
+
function syncSkillsToTarget(srcSkillsDir, destSkillsDir, ownershipPrefixes, namePrefix) {
|
|
2339
|
+
if (!existsSync$1(srcSkillsDir)) return 0;
|
|
2340
|
+
mkdirSync$1(destSkillsDir, { recursive: true });
|
|
2341
|
+
const sourceEntries = readdirSync$1(srcSkillsDir, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
2342
|
+
const destNames = new Set(sourceEntries.map((e) => namePrefix && !e.name.startsWith(namePrefix) ? `${namePrefix}${e.name}` : e.name));
|
|
2343
|
+
try {
|
|
2344
|
+
for (const entry of readdirSync$1(destSkillsDir, { withFileTypes: true })) {
|
|
2345
|
+
if (!entry.isDirectory()) continue;
|
|
2346
|
+
const isOwned = ownershipPrefixes.some((p) => entry.name.startsWith(p));
|
|
2347
|
+
if (!isOwned) continue;
|
|
2348
|
+
if (destNames.has(entry.name)) continue;
|
|
2349
|
+
rmSync$1(join(destSkillsDir, entry.name), {
|
|
2350
|
+
recursive: true,
|
|
2351
|
+
force: true
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
} catch (err) {
|
|
2355
|
+
logger$15.debug({
|
|
2356
|
+
err,
|
|
2357
|
+
destSkillsDir
|
|
2358
|
+
}, "Failed to prune stale skills");
|
|
2359
|
+
}
|
|
2360
|
+
let count = 0;
|
|
2361
|
+
for (const entry of sourceEntries) {
|
|
2362
|
+
const destName = namePrefix && !entry.name.startsWith(namePrefix) ? `${namePrefix}${entry.name}` : entry.name;
|
|
2363
|
+
const dest = join(destSkillsDir, destName);
|
|
2364
|
+
rmSync$1(dest, {
|
|
2365
|
+
recursive: true,
|
|
2366
|
+
force: true
|
|
2367
|
+
});
|
|
2368
|
+
cpSync(join(srcSkillsDir, entry.name), dest, { recursive: true });
|
|
2369
|
+
count++;
|
|
2370
|
+
}
|
|
2371
|
+
return count;
|
|
2372
|
+
}
|
|
2373
|
+
const PROJECT_OWNERSHIP_PREFIXES = ["bmad-", "substrate-"];
|
|
2374
|
+
/**
|
|
2375
|
+
* Scaffold project-scoped Codex content from the already-generated
|
|
2376
|
+
* `.claude/commands/` and `.claude/skills/`. Must run AFTER
|
|
2377
|
+
* `scaffoldClaudeCommands`.
|
|
2378
|
+
*
|
|
2379
|
+
* Writes:
|
|
2380
|
+
* - <projectRoot>/.codex/prompts/*.md (slash commands)
|
|
2381
|
+
* - <projectRoot>/.codex/skills/<skill>/ (skill bundles)
|
|
2382
|
+
*
|
|
2383
|
+
* Stale substrate-owned entries (bmad-*, substrate-*) from previous runs are
|
|
2384
|
+
* pruned before new content is written. Non-owned files (e.g., `ship.md` from
|
|
2385
|
+
* a plugin) are left alone.
|
|
2386
|
+
*/
|
|
2387
|
+
function scaffoldCodexProject(projectRoot, outputFormat) {
|
|
2388
|
+
const claudeCommandsDir = join(projectRoot, ".claude", "commands");
|
|
2389
|
+
const claudeSkillsDir = join(projectRoot, ".claude", "skills");
|
|
2390
|
+
const codexDir = join(projectRoot, ".codex");
|
|
2391
|
+
const codexPromptsDir = join(codexDir, "prompts");
|
|
2392
|
+
const codexSkillsDir = join(codexDir, "skills");
|
|
2393
|
+
try {
|
|
2394
|
+
const promptCount = syncCommandsAsPrompts(claudeCommandsDir, codexPromptsDir, PROJECT_OWNERSHIP_PREFIXES, "");
|
|
2395
|
+
const skillCount = syncSkillsToTarget(claudeSkillsDir, codexSkillsDir, PROJECT_OWNERSHIP_PREFIXES, "");
|
|
2396
|
+
const total = promptCount + skillCount;
|
|
2397
|
+
if (outputFormat !== "json" && total > 0) process.stdout.write(`Generated ${String(total)} Codex artifacts (${String(promptCount)} prompts, ${String(skillCount)} skills)\n`);
|
|
2398
|
+
if (total > 0) logger$15.info({
|
|
2399
|
+
promptCount,
|
|
2400
|
+
skillCount,
|
|
2401
|
+
codexDir
|
|
2402
|
+
}, "Generated .codex/");
|
|
2403
|
+
else logger$15.debug({ codexDir }, "No Codex artifacts generated; source Claude content not found");
|
|
2404
|
+
} catch (err) {
|
|
2405
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2406
|
+
if (outputFormat !== "json") process.stderr.write(`Warning: .codex/ generation failed: ${msg}\n`);
|
|
2407
|
+
logger$15.warn({ err }, "scaffoldCodexProject failed; init continues");
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
/**
|
|
2411
|
+
* Install Codex content user-wide at `~/.codex/`, namespaced under
|
|
2412
|
+
* `substrate-` to avoid colliding with user-installed content.
|
|
2413
|
+
*
|
|
2414
|
+
* Writes:
|
|
2415
|
+
* - ~/.codex/prompts/substrate-<slug>.md (slash commands)
|
|
2416
|
+
* - ~/.codex/skills/substrate-<name>/ (skill bundles)
|
|
2417
|
+
*
|
|
2418
|
+
* Stale `substrate-*` entries from previous runs are pruned before new
|
|
2419
|
+
* content is written. Files/directories without the `substrate-` prefix
|
|
2420
|
+
* are never touched.
|
|
2421
|
+
*/
|
|
2422
|
+
function scaffoldCodexUser(projectRoot, homeDir, outputFormat) {
|
|
2423
|
+
const claudeCommandsDir = join(projectRoot, ".claude", "commands");
|
|
2424
|
+
const claudeSkillsDir = join(projectRoot, ".claude", "skills");
|
|
2425
|
+
const userCodexDir = join(homeDir, ".codex");
|
|
2426
|
+
const userPromptsDir = join(userCodexDir, "prompts");
|
|
2427
|
+
const userSkillsDir = join(userCodexDir, "skills");
|
|
2428
|
+
try {
|
|
2429
|
+
const promptCount = syncCommandsAsPrompts(claudeCommandsDir, userPromptsDir, ["substrate-"], "substrate-");
|
|
2430
|
+
const skillCount = syncSkillsToTarget(claudeSkillsDir, userSkillsDir, ["substrate-"], "substrate-");
|
|
2431
|
+
const total = promptCount + skillCount;
|
|
2432
|
+
if (outputFormat !== "json" && total > 0) process.stdout.write(`Installed ${String(total)} Codex artifacts to ${userCodexDir} (${String(promptCount)} prompts, ${String(skillCount)} skills)\n`);
|
|
2433
|
+
if (total > 0) logger$15.info({
|
|
2434
|
+
promptCount,
|
|
2435
|
+
skillCount,
|
|
2436
|
+
userCodexDir
|
|
2437
|
+
}, "Installed user-scope Codex content");
|
|
2438
|
+
else logger$15.debug({ userCodexDir }, "No user-scope Codex content installed; source Claude content not found");
|
|
2439
|
+
} catch (err) {
|
|
2440
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2441
|
+
if (outputFormat !== "json") process.stderr.write(`Warning: user-scope Codex install failed: ${msg}\n`);
|
|
2442
|
+
logger$15.warn({ err }, "scaffoldCodexUser failed; init continues");
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2287
2445
|
const PROVIDER_DEFAULTS = DEFAULT_CONFIG.providers;
|
|
2288
2446
|
const ADAPTER_TO_PROVIDER = {
|
|
2289
2447
|
"claude-code": "claude",
|
|
@@ -2512,6 +2670,12 @@ async function runInitAction(options) {
|
|
|
2512
2670
|
await scaffoldStatuslineScript(projectRoot);
|
|
2513
2671
|
await scaffoldClaudeSettings(projectRoot);
|
|
2514
2672
|
await scaffoldClaudeCommands(projectRoot, outputFormat);
|
|
2673
|
+
scaffoldCodexProject(projectRoot, outputFormat);
|
|
2674
|
+
if (options.installUserScope) {
|
|
2675
|
+
const homeDir = process.env["HOME"] ?? process.env["USERPROFILE"];
|
|
2676
|
+
if (homeDir) scaffoldCodexUser(projectRoot, homeDir, outputFormat);
|
|
2677
|
+
else if (outputFormat !== "json") process.stderr.write("Warning: --install-user-scope requested but HOME/USERPROFILE is not set\n");
|
|
2678
|
+
}
|
|
2515
2679
|
const gitignorePath = join(projectRoot, ".gitignore");
|
|
2516
2680
|
const runtimeEntries = [
|
|
2517
2681
|
".substrate/orchestrator.pid",
|
|
@@ -2519,7 +2683,9 @@ async function runInitAction(options) {
|
|
|
2519
2683
|
".substrate/scenarios/",
|
|
2520
2684
|
".substrate/state/",
|
|
2521
2685
|
".substrate/substrate.db",
|
|
2522
|
-
".substrate/substrate.db-journal"
|
|
2686
|
+
".substrate/substrate.db-journal",
|
|
2687
|
+
".codex/prompts/",
|
|
2688
|
+
".codex/skills/"
|
|
2523
2689
|
];
|
|
2524
2690
|
try {
|
|
2525
2691
|
const existing = existsSync$1(gitignorePath) ? readFileSync$1(gitignorePath, "utf-8") : "";
|
|
@@ -2583,6 +2749,8 @@ async function runInitAction(options) {
|
|
|
2583
2749
|
process.stdout.write(` AGENTS.md pipeline instructions for Codex CLI\n`);
|
|
2584
2750
|
process.stdout.write(` GEMINI.md pipeline instructions for Gemini CLI\n`);
|
|
2585
2751
|
process.stdout.write(` .claude/commands/ /substrate-run, /substrate-supervisor, /substrate-metrics\n`);
|
|
2752
|
+
process.stdout.write(` .codex/prompts/ Codex slash commands (mirror of .claude/commands/)\n`);
|
|
2753
|
+
process.stdout.write(` .codex/skills/ Codex skill bundles (mirror of .claude/skills/)\n`);
|
|
2586
2754
|
process.stdout.write(` .substrate/ config, database, routing policy\n`);
|
|
2587
2755
|
if (doltInitialized) process.stdout.write(`✓ Dolt state store initialized at .substrate/state/\n`);
|
|
2588
2756
|
else if (doltMode !== "skip") process.stdout.write(`ℹ Dolt not detected — install Dolt for versioned state, \`substrate diff\`, and observability persistence. See: https://docs.dolthub.com/introduction/installation\n`);
|
|
@@ -2598,7 +2766,7 @@ async function runInitAction(options) {
|
|
|
2598
2766
|
}
|
|
2599
2767
|
}
|
|
2600
2768
|
function registerInitCommand(program, _version, registry) {
|
|
2601
|
-
program.command("init").description("Initialize Substrate — creates config, scaffolds methodology pack, and sets up database").option("--pack <name>", "Methodology pack name", "bmad").option("--project-root <path>", "Project root directory", process.cwd()).option("-y, --yes", "Skip all interactive prompts and use defaults", false).option("--force", "Overwrite existing files and packs", false).option("--output-format <format>", "Output format: human (default) or json", "human").option("--dolt", "Initialize Dolt state database as part of init (forces Dolt bootstrapping)", false).option("--no-dolt", "Skip Dolt state store initialization even if Dolt is installed").action(async (opts) => {
|
|
2769
|
+
program.command("init").description("Initialize Substrate — creates config, scaffolds methodology pack, and sets up database").option("--pack <name>", "Methodology pack name", "bmad").option("--project-root <path>", "Project root directory", process.cwd()).option("-y, --yes", "Skip all interactive prompts and use defaults", false).option("--force", "Overwrite existing files and packs", false).option("--output-format <format>", "Output format: human (default) or json", "human").option("--dolt", "Initialize Dolt state database as part of init (forces Dolt bootstrapping)", false).option("--no-dolt", "Skip Dolt state store initialization even if Dolt is installed").option("--install-user-scope", "Also install Codex prompts/skills into ~/.codex/ (namespaced substrate-*)", false).action(async (opts) => {
|
|
2602
2770
|
const outputFormat = opts.outputFormat === "json" ? "json" : "human";
|
|
2603
2771
|
const doltMode = opts.noDolt ? "skip" : opts.dolt ? "force" : "auto";
|
|
2604
2772
|
const exitCode = await runInitAction({
|
|
@@ -2608,6 +2776,7 @@ function registerInitCommand(program, _version, registry) {
|
|
|
2608
2776
|
force: opts.force,
|
|
2609
2777
|
yes: opts.yes,
|
|
2610
2778
|
doltMode,
|
|
2779
|
+
installUserScope: opts.installUserScope,
|
|
2611
2780
|
...registry !== void 0 && { registry }
|
|
2612
2781
|
});
|
|
2613
2782
|
process.exitCode = exitCode;
|
|
@@ -5022,7 +5191,7 @@ async function runSupervisorAction(options, deps = {}) {
|
|
|
5022
5191
|
await initSchema(expAdapter);
|
|
5023
5192
|
const { runRunAction: runPipeline } = await import(
|
|
5024
5193
|
/* @vite-ignore */
|
|
5025
|
-
"../run-
|
|
5194
|
+
"../run-BwMDKH66.js"
|
|
5026
5195
|
);
|
|
5027
5196
|
const runStoryFn = async (opts) => {
|
|
5028
5197
|
const exitCode = await runPipeline({
|
|
@@ -13374,7 +13374,8 @@ function createImplementationOrchestrator(deps) {
|
|
|
13374
13374
|
workingDirectory: projectRoot,
|
|
13375
13375
|
pipelineRunId: config.pipelineRunId,
|
|
13376
13376
|
filesModified: group.files,
|
|
13377
|
-
buildPassed: _buildPassed
|
|
13377
|
+
buildPassed: _buildPassed,
|
|
13378
|
+
...baselineHeadSha ? { baselineCommit: baselineHeadSha } : {}
|
|
13378
13379
|
});
|
|
13379
13380
|
if (batchReview.tokenUsage) {
|
|
13380
13381
|
aggregateTokens.input += batchReview.tokenUsage.input;
|
|
@@ -43076,4 +43077,4 @@ function registerRunCommand(program, _version = "0.0.0", projectRoot = process.c
|
|
|
43076
43077
|
|
|
43077
43078
|
//#endregion
|
|
43078
43079
|
export { AdapterTelemetryPersistence, AppError, DoltRepoMapMetaRepository, DoltSymbolRepository, ERR_REPO_MAP_STORAGE_WRITE, EpicIngester, GitClient, GrammarLoader, RepoMapInjector, RepoMapModule, RepoMapQueryEngine, RepoMapStorage, SymbolParser, createContextCompiler, createDispatcher, createEventEmitter, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, createTelemetryAdvisor, formatPhaseCompletionSummary, getFactoryRunSummaries, getScenarioResultsForRun, getTwinRunsForRun, listGraphRuns, normalizeGraphSummaryToStatus, registerExportCommand, registerFactoryCommand, registerRunCommand, registerScenariosCommand, resolveMaxReviewCycles, resolveStoryKeys, runAnalysisPhase, runPlanningPhase, runRunAction, runSolutioningPhase, validateStopAfterFromConflict, wireNdjsonEmitter };
|
|
43079
|
-
//# sourceMappingURL=run-
|
|
43080
|
+
//# sourceMappingURL=run-BUKozIHS.js.map
|
|
@@ -2,7 +2,7 @@ import "./health-DrZiqv4h.js";
|
|
|
2
2
|
import "./logger-KeHncl-f.js";
|
|
3
3
|
import "./helpers-CElYrONe.js";
|
|
4
4
|
import "./dist-sNh9XQ6V.js";
|
|
5
|
-
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-
|
|
5
|
+
import { normalizeGraphSummaryToStatus, registerRunCommand, resolveMaxReviewCycles, runRunAction, wireNdjsonEmitter } from "./run-BUKozIHS.js";
|
|
6
6
|
import "./routing-CcBOCuC9.js";
|
|
7
7
|
import "./decisions-C0pz9Clx.js";
|
|
8
8
|
|