@evo-dev/core 0.0.1-alpha.2 → 0.0.1-alpha.3

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/index.js CHANGED
@@ -7360,7 +7360,7 @@ function isRecord6(value) {
7360
7360
  // packages/core/src/team/index.ts
7361
7361
  import { spawn } from "node:child_process";
7362
7362
  import { appendFile as appendFile2, cp, mkdir as mkdir6, readFile as readFile7, readdir as readdir5, stat as stat6, writeFile as writeFile5 } from "node:fs/promises";
7363
- import { basename as basename3, dirname as dirname6, join as join7 } from "node:path";
7363
+ import { basename as basename3, dirname as dirname6, extname, isAbsolute as isAbsolute5, join as join7, relative as relative6, resolve as resolve4 } from "node:path";
7364
7364
 
7365
7365
  // packages/core/src/team/prompts.ts
7366
7366
  var TEAM_ROLE_STARTUP_PROMPT_TEMPLATE = [
@@ -7538,6 +7538,23 @@ var BUILT_IN_ROLE_PROMPTS = {
7538
7538
  prompt: "You are the implementation executor for this EvoDev team run. Keep changes scoped, avoid taking conductor decisions, and report changed files plus verification evidence."
7539
7539
  }
7540
7540
  };
7541
+ var BUILT_IN_TEAM_DEFINITION = {
7542
+ version: 1,
7543
+ name: "builtin-minimal-team",
7544
+ description: "Built-in minimal EvoDev team fallback.",
7545
+ agents: {
7546
+ executor: "builtin:executor",
7547
+ reviewer: "builtin:reviewer",
7548
+ tester: "builtin:tester"
7549
+ },
7550
+ body: [
7551
+ "# Built-in Minimal Team",
7552
+ "",
7553
+ "Use role agents only when delegation improves correctness, coverage, safety, or latency.",
7554
+ "Spawn roles on demand and send self-contained assignments through Teams MCP."
7555
+ ].join(`
7556
+ `)
7557
+ };
7541
7558
  function createTeamRunStore(homeDir) {
7542
7559
  const paths = resolveTeamRunPaths(homeDir);
7543
7560
  return {
@@ -8541,9 +8558,188 @@ async function listTeamAgents(input = {}) {
8541
8558
  isMidTurn: isMidTurnTeamAgentStatus(agent.status)
8542
8559
  }));
8543
8560
  }
8561
+ async function resolveTeamOverlay(input) {
8562
+ const repoTeamPath = join7(input.repoRoot, ".evodev", "team", "team.md");
8563
+ if (await pathExists5(repoTeamPath)) {
8564
+ return {
8565
+ source: "repo",
8566
+ teamPath: repoTeamPath,
8567
+ definition: parseTeamDefinitionMarkdown(await readFile7(repoTeamPath, "utf8"))
8568
+ };
8569
+ }
8570
+ const globalTeamPath = resolveGlobalTeamMarkdownPath(input.homeDir);
8571
+ if (await pathExists5(globalTeamPath)) {
8572
+ return {
8573
+ source: "global",
8574
+ teamPath: globalTeamPath,
8575
+ definition: parseTeamDefinitionMarkdown(await readFile7(globalTeamPath, "utf8"))
8576
+ };
8577
+ }
8578
+ return {
8579
+ source: "builtin",
8580
+ teamPath: null,
8581
+ definition: BUILT_IN_TEAM_DEFINITION
8582
+ };
8583
+ }
8584
+ async function ensureDefaultTeamOverlay(input) {
8585
+ const assets = await listDefaultTeamOverlayAssets(input.assetsRootDir);
8586
+ const paths = resolveEvoDevPaths(input.homeDir);
8587
+ const files = [];
8588
+ for (const asset of assets) {
8589
+ const targetPath = asset.kind === "team" ? join7(paths.rootDir, "team", "team.md") : join7(paths.rootDir, "team", "agents", asset.name);
8590
+ const content = await readFile7(asset.sourcePath, "utf8");
8591
+ files.push({
8592
+ sourcePath: asset.sourcePath,
8593
+ targetPath,
8594
+ written: await writeTextFileIfMissing(targetPath, content)
8595
+ });
8596
+ }
8597
+ return { files };
8598
+ }
8599
+ function parseTeamDefinitionMarkdown(content) {
8600
+ const markdown = parseMarkdownWithFrontmatter(content);
8601
+ const frontmatter = markdown.frontmatter;
8602
+ const version = frontmatter.version;
8603
+ if (version !== 1)
8604
+ throw new Error("team.md frontmatter version must be 1.");
8605
+ const agents = parseTeamDefinitionAgents(frontmatter.agents);
8606
+ return {
8607
+ version: 1,
8608
+ name: optionalString4(frontmatter.name) ?? "evodev-team",
8609
+ description: optionalString4(frontmatter.description) ?? "EvoDev team overlay.",
8610
+ agents,
8611
+ body: markdown.body.trim()
8612
+ };
8613
+ }
8614
+ function resolveTeamAgentReference(input) {
8615
+ assertSafeId(input.roleId, "roleId");
8616
+ const reference = input.reference.trim();
8617
+ if (reference.startsWith("global:")) {
8618
+ const name = reference.slice("global:".length);
8619
+ assertSafeId(name, "global agent name");
8620
+ return {
8621
+ roleId: input.roleId,
8622
+ reference,
8623
+ sourcePath: join7(resolveEvoDevPaths(input.homeDir).rootDir, "team", "agents", `${name}.md`),
8624
+ scope: "global"
8625
+ };
8626
+ }
8627
+ if (reference.includes(":")) {
8628
+ throw new Error(`Unsupported team agent reference for ${input.roleId}: ${reference}`);
8629
+ }
8630
+ if (isAbsolute5(reference)) {
8631
+ throw new Error(`Team agent path for ${input.roleId} must be repo-relative.`);
8632
+ }
8633
+ const sourcePath = resolve4(input.repoRoot, reference);
8634
+ const relativePath = relative6(input.repoRoot, sourcePath);
8635
+ if (relativePath === "" || relativePath.startsWith("..") || isAbsolute5(relativePath) || extname(sourcePath) !== ".md") {
8636
+ throw new Error(`Team agent path for ${input.roleId} must be a repo-local Markdown file.`);
8637
+ }
8638
+ return {
8639
+ roleId: input.roleId,
8640
+ reference,
8641
+ sourcePath,
8642
+ scope: "repo"
8643
+ };
8644
+ }
8645
+ async function readTeamAgentSummary(input) {
8646
+ const reference = resolveTeamAgentReference(input);
8647
+ const markdown = await readTeamAgentMarkdown(reference);
8648
+ const parsed = parseMarkdownWithFrontmatter(markdown);
8649
+ return {
8650
+ roleId: input.roleId,
8651
+ name: optionalString4(parsed.frontmatter.name) ?? defaultRoleName(input.roleId),
8652
+ description: optionalString4(parsed.frontmatter.description) ?? `EvoDev ${input.roleId} role agent.`,
8653
+ sourcePath: reference.sourcePath
8654
+ };
8655
+ }
8656
+ async function readTeamAgentDefinition(input) {
8657
+ const reference = resolveTeamAgentReference(input);
8658
+ const markdown = await readTeamAgentMarkdown(reference);
8659
+ const parsed = parseMarkdownWithFrontmatter(markdown);
8660
+ const evodev = isRecord7(parsed.frontmatter.evodev) ? parsed.frontmatter.evodev : {};
8661
+ return {
8662
+ roleId: input.roleId,
8663
+ name: optionalString4(parsed.frontmatter.name) ?? defaultRoleName(input.roleId),
8664
+ description: optionalString4(parsed.frontmatter.description) ?? `EvoDev ${input.roleId} role agent.`,
8665
+ runtime: optionalRuntime(evodev.runtime),
8666
+ model: optionalNullableString(parsed.frontmatter.model) ?? null,
8667
+ thinkingLevel: optionalNullableString(evodev.thinking) ?? optionalNullableString(evodev.thinkingLevel) ?? null,
8668
+ writeMode: optionalWriteMode(evodev.writeMode),
8669
+ skills: parseStringList(evodev.skills),
8670
+ sourcePath: reference.sourcePath,
8671
+ markdown
8672
+ };
8673
+ }
8674
+ async function renderMainTeamOverlayContext(input) {
8675
+ const overlay = input.overlay ?? await resolveTeamOverlay(input);
8676
+ const summaries = await readTeamOverlayAgentSummaries({
8677
+ homeDir: input.homeDir,
8678
+ repoRoot: input.repoRoot,
8679
+ overlay
8680
+ });
8681
+ const roleLines = summaries.length === 0 ? ["- none declared"] : summaries.map((summary) => `- ${summary.roleId}: ${summary.name} - ${summary.description}`);
8682
+ const source = overlay.teamPath === null ? `${overlay.source} fallback` : `${overlay.source}: ${overlay.teamPath}`;
8683
+ return [
8684
+ "EvoDev team overlay:",
8685
+ `Team: ${overlay.definition.name}`,
8686
+ `Description: ${overlay.definition.description}`,
8687
+ `Source: ${source}`,
8688
+ "",
8689
+ "Team strategy:",
8690
+ overlay.definition.body || "(none)",
8691
+ "",
8692
+ "Declared role agents:",
8693
+ ...roleLines,
8694
+ "",
8695
+ "Overlay rules:",
8696
+ "- Declared role agents are spawned only on demand.",
8697
+ "- Delegate by role id; role agent Markdown is loaded only inside the spawned role."
8698
+ ].join(`
8699
+ `);
8700
+ }
8701
+ function renderRoleAgentDefinitionContext(input) {
8702
+ return [
8703
+ "EvoDev role agent Markdown definition:",
8704
+ `Source path: ${input.definition.sourcePath}`,
8705
+ "Use this Markdown as the role-specific operating definition for this role only.",
8706
+ "<evodev-agent-markdown>",
8707
+ input.definition.markdown.trimEnd(),
8708
+ "</evodev-agent-markdown>"
8709
+ ].join(`
8710
+ `);
8711
+ }
8544
8712
  async function resolveTeamRole(input) {
8545
8713
  assertSafeId(input.roleId, "roleId");
8546
8714
  const settings = await readSettingsOrDefault(input.homeDir);
8715
+ const overlay = await resolveTeamOverlay({ homeDir: input.homeDir, repoRoot: input.repoRoot });
8716
+ if (overlay.source !== "builtin" && input.roleId !== "main") {
8717
+ const reference = overlay.definition.agents[input.roleId];
8718
+ if (reference === undefined) {
8719
+ throw new Error(`Role ${input.roleId} is not declared in team overlay ${overlay.teamPath ?? overlay.source}.`);
8720
+ }
8721
+ const agent = await readTeamAgentDefinition({
8722
+ homeDir: input.homeDir,
8723
+ repoRoot: input.repoRoot,
8724
+ roleId: input.roleId,
8725
+ reference
8726
+ });
8727
+ return {
8728
+ version: 1,
8729
+ roleId: input.roleId,
8730
+ roleName: agent.name,
8731
+ description: agent.description,
8732
+ runtime: agent.runtime ?? settings.teamRuntime.defaultRuntime,
8733
+ model: agent.model ?? settings.teamRuntime.defaultModel,
8734
+ thinkingLevel: agent.thinkingLevel ?? settings.teamRuntime.defaultThinkingLevel,
8735
+ prompt: renderRoleAgentDefinitionContext({ definition: agent }),
8736
+ permissions: parseRolePermissions({ writeMode: agent.writeMode ?? undefined }, false),
8737
+ teamPolicy: parseRolePolicy(undefined, settings.teamRuntime.recordTranscript),
8738
+ source: "overlay",
8739
+ sourcePath: agent.sourcePath,
8740
+ nativeAgent: null
8741
+ };
8742
+ }
8547
8743
  const globalRolePath = join7(resolveEvoDevPaths(input.homeDir).roleAgentsDir, `${input.roleId}.json`);
8548
8744
  const candidate = await readRoleCandidate(globalRolePath, "global");
8549
8745
  const nativeAgent = await resolveTeamRoleNativeAgentBinding({
@@ -8562,11 +8758,17 @@ async function resolveTeamRole(input) {
8562
8758
  defaultThinkingLevel: settings.teamRuntime.defaultThinkingLevel,
8563
8759
  recordTranscript: settings.teamRuntime.recordTranscript
8564
8760
  });
8761
+ const prompt = input.roleId === "main" ? appendPromptBlock(parsed.prompt, await renderMainTeamOverlayContext({
8762
+ homeDir: input.homeDir,
8763
+ repoRoot: input.repoRoot,
8764
+ overlay
8765
+ })) : parsed.prompt;
8565
8766
  return {
8566
8767
  ...parsed,
8567
8768
  runtime: input.overrides?.runtime ?? nativeAgent?.target ?? parsed.runtime,
8568
8769
  model: input.overrides?.model ?? parsed.model,
8569
8770
  thinkingLevel: input.overrides?.thinkingLevel ?? parsed.thinkingLevel,
8771
+ prompt,
8570
8772
  sourcePath,
8571
8773
  nativeAgent
8572
8774
  };
@@ -8796,7 +8998,7 @@ class TmuxRuntimeAdapter {
8796
8998
 
8797
8999
  class NodeTeamRuntimeCommandRunner {
8798
9000
  async run(command, args, options = {}) {
8799
- return new Promise((resolve4, reject) => {
9001
+ return new Promise((resolve5, reject) => {
8800
9002
  const child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"] });
8801
9003
  let stdout = "";
8802
9004
  let stderr = "";
@@ -8810,7 +9012,7 @@ class NodeTeamRuntimeCommandRunner {
8810
9012
  });
8811
9013
  child.once("error", reject);
8812
9014
  child.once("close", (code) => {
8813
- resolve4({ exitCode: code ?? 1, stdout, stderr });
9015
+ resolve5({ exitCode: code ?? 1, stdout, stderr });
8814
9016
  });
8815
9017
  child.stdin.end(options.input ?? "");
8816
9018
  });
@@ -9075,6 +9277,206 @@ function createBuiltInRole(roleId, runtime) {
9075
9277
  prompt: builtin?.prompt ?? defaultRolePrompt(roleId)
9076
9278
  };
9077
9279
  }
9280
+ async function readTeamOverlayAgentSummaries(input) {
9281
+ const entries = Object.entries(input.overlay.definition.agents);
9282
+ if (input.overlay.source === "builtin") {
9283
+ return entries.map(([roleId]) => {
9284
+ const builtin = BUILT_IN_ROLE_PROMPTS[roleId];
9285
+ return {
9286
+ roleId,
9287
+ name: builtin?.roleName ?? defaultRoleName(roleId),
9288
+ description: builtin?.description ?? `EvoDev ${roleId} role agent.`,
9289
+ sourcePath: "builtin"
9290
+ };
9291
+ });
9292
+ }
9293
+ return Promise.all(entries.map(([roleId, reference]) => readTeamAgentSummary({
9294
+ homeDir: input.homeDir,
9295
+ repoRoot: input.repoRoot,
9296
+ roleId,
9297
+ reference
9298
+ })));
9299
+ }
9300
+ async function listDefaultTeamOverlayAssets(assetsRootDir) {
9301
+ const teamPath = join7(assetsRootDir, "team", "team.md");
9302
+ const agentsDir = join7(assetsRootDir, "team", "agents");
9303
+ await assertReadableFile(teamPath, "Default team asset");
9304
+ let entries;
9305
+ try {
9306
+ entries = await readdir5(agentsDir, { withFileTypes: true });
9307
+ } catch (error) {
9308
+ throw new Error(`Cannot read default team agents directory ${agentsDir}: ${describeError2(error)}`);
9309
+ }
9310
+ const agentFiles = entries.filter((entry) => entry.isFile() && extname(entry.name) === ".md").map((entry) => entry.name).sort();
9311
+ if (agentFiles.length === 0) {
9312
+ throw new Error(`Default team agents directory has no Markdown files: ${agentsDir}`);
9313
+ }
9314
+ return [
9315
+ { kind: "team", sourcePath: teamPath, name: "team.md" },
9316
+ ...agentFiles.map((name) => ({
9317
+ kind: "agent",
9318
+ sourcePath: join7(agentsDir, name),
9319
+ name
9320
+ }))
9321
+ ];
9322
+ }
9323
+ async function assertReadableFile(path, label) {
9324
+ try {
9325
+ const info = await stat6(path);
9326
+ if (!info.isFile())
9327
+ throw new Error("not a file");
9328
+ } catch (error) {
9329
+ throw new Error(`${label} is not readable at ${path}: ${describeError2(error)}`);
9330
+ }
9331
+ }
9332
+ async function writeTextFileIfMissing(path, content) {
9333
+ try {
9334
+ await readFile7(path, "utf8");
9335
+ return false;
9336
+ } catch (error) {
9337
+ if (!isNotFoundError2(error)) {
9338
+ throw new Error(`Cannot inspect ${path}: ${describeError2(error)}`);
9339
+ }
9340
+ }
9341
+ await mkdir6(dirname6(path), { recursive: true });
9342
+ await writeFile5(path, content.endsWith(`
9343
+ `) ? content : `${content}
9344
+ `, "utf8");
9345
+ return true;
9346
+ }
9347
+ function parseTeamDefinitionAgents(value) {
9348
+ if (value === undefined)
9349
+ return {};
9350
+ if (!isRecord7(value))
9351
+ throw new Error("team.md agents must be a role-id map.");
9352
+ const agents = {};
9353
+ for (const [roleId, reference] of Object.entries(value)) {
9354
+ assertSafeId(roleId, "team.md agents roleId");
9355
+ if (typeof reference !== "string" || reference.trim() === "") {
9356
+ throw new Error(`team.md agent reference for ${roleId} must be a non-empty string.`);
9357
+ }
9358
+ agents[roleId] = reference.trim();
9359
+ }
9360
+ return agents;
9361
+ }
9362
+ async function readTeamAgentMarkdown(reference) {
9363
+ if (extname(reference.sourcePath) !== ".md") {
9364
+ throw new Error(`Team agent file for ${reference.roleId} must be Markdown.`);
9365
+ }
9366
+ try {
9367
+ return await readFile7(reference.sourcePath, "utf8");
9368
+ } catch (error) {
9369
+ if (isNotFoundError2(error)) {
9370
+ throw new Error(`Team agent file not found for ${reference.roleId}: ${reference.sourcePath}`);
9371
+ }
9372
+ throw new Error(`Cannot read team agent file for ${reference.roleId}: ${reference.sourcePath}: ${describeError2(error)}`);
9373
+ }
9374
+ }
9375
+ function parseMarkdownWithFrontmatter(content) {
9376
+ const text = content.startsWith("\uFEFF") ? content.slice(1) : content;
9377
+ const lines = text.split(/\r?\n/);
9378
+ if (lines[0]?.trim() !== "---")
9379
+ return { frontmatter: {}, body: text };
9380
+ const end = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
9381
+ if (end < 0)
9382
+ throw new Error("Markdown frontmatter is not closed.");
9383
+ return {
9384
+ frontmatter: parseSimpleYaml(lines.slice(1, end).join(`
9385
+ `)),
9386
+ body: lines.slice(end + 1).join(`
9387
+ `)
9388
+ };
9389
+ }
9390
+ function parseSimpleYaml(content) {
9391
+ const root = {};
9392
+ const stack = [
9393
+ { indent: -1, value: root }
9394
+ ];
9395
+ const lines = content.split(/\r?\n/);
9396
+ for (let index = 0;index < lines.length; index += 1) {
9397
+ const rawLine = lines[index] ?? "";
9398
+ if (rawLine.trim() === "" || rawLine.trimStart().startsWith("#"))
9399
+ continue;
9400
+ const indent = rawLine.match(/^ */)?.[0].length ?? 0;
9401
+ const trimmed = rawLine.trim();
9402
+ while (stack.length > 1 && indent <= stack[stack.length - 1].indent)
9403
+ stack.pop();
9404
+ const parent = stack[stack.length - 1].value;
9405
+ if (trimmed.startsWith("- ")) {
9406
+ if (!Array.isArray(parent))
9407
+ throw new Error("Invalid YAML list item placement.");
9408
+ parent.push(parseYamlScalar(trimmed.slice(2).trim()));
9409
+ continue;
9410
+ }
9411
+ const separator = trimmed.indexOf(":");
9412
+ if (separator <= 0)
9413
+ throw new Error(`Invalid YAML line: ${trimmed}`);
9414
+ const key = trimmed.slice(0, separator).trim();
9415
+ const rawValue = trimmed.slice(separator + 1).trim();
9416
+ if (!isRecord7(parent))
9417
+ throw new Error(`Invalid YAML parent for key ${key}.`);
9418
+ if (rawValue === "") {
9419
+ const next = findNextYamlContentLine(lines, index + 1);
9420
+ const value = next !== null && next.indent > indent && next.trimmed.startsWith("- ") ? [] : {};
9421
+ parent[key] = value;
9422
+ stack.push({ indent, value });
9423
+ continue;
9424
+ }
9425
+ parent[key] = parseYamlScalar(rawValue);
9426
+ }
9427
+ return root;
9428
+ }
9429
+ function findNextYamlContentLine(lines, start) {
9430
+ for (let index = start;index < lines.length; index += 1) {
9431
+ const line = lines[index] ?? "";
9432
+ if (line.trim() === "" || line.trimStart().startsWith("#"))
9433
+ continue;
9434
+ return {
9435
+ indent: line.match(/^ */)?.[0].length ?? 0,
9436
+ trimmed: line.trim()
9437
+ };
9438
+ }
9439
+ return null;
9440
+ }
9441
+ function parseYamlScalar(value) {
9442
+ if (value === "")
9443
+ return "";
9444
+ if (value === "true")
9445
+ return true;
9446
+ if (value === "false")
9447
+ return false;
9448
+ if (value === "null" || value === "~")
9449
+ return null;
9450
+ if (/^-?\d+(\.\d+)?$/.test(value))
9451
+ return Number(value);
9452
+ if (value.startsWith("[") && value.endsWith("]")) {
9453
+ const inner = value.slice(1, -1).trim();
9454
+ if (inner === "")
9455
+ return [];
9456
+ return inner.split(",").map((item) => parseYamlScalar(item.trim()));
9457
+ }
9458
+ if (value.startsWith('"') && value.endsWith('"')) {
9459
+ try {
9460
+ return JSON.parse(value);
9461
+ } catch {
9462
+ return value.slice(1, -1);
9463
+ }
9464
+ }
9465
+ if (value.startsWith("'") && value.endsWith("'")) {
9466
+ return value.slice(1, -1).replace(/''/g, "'");
9467
+ }
9468
+ return value;
9469
+ }
9470
+ function appendPromptBlock(prompt, block) {
9471
+ if (block.trim() === "")
9472
+ return prompt;
9473
+ return `${prompt.trimEnd()}
9474
+
9475
+ ${block.trim()}`;
9476
+ }
9477
+ function resolveGlobalTeamMarkdownPath(homeDir) {
9478
+ return join7(resolveEvoDevPaths(homeDir).rootDir, "team", "team.md");
9479
+ }
9078
9480
  function parseRolePermissions(value, main) {
9079
9481
  const input = isRecord7(value) ? value : {};
9080
9482
  return {
@@ -9187,6 +9589,13 @@ function parseRuntime(value, fallback) {
9187
9589
  return value;
9188
9590
  throw new Error("Role runtime must be codex or claude.");
9189
9591
  }
9592
+ function optionalRuntime(value) {
9593
+ if (value === undefined || value === null)
9594
+ return null;
9595
+ if (value === "codex" || value === "claude")
9596
+ return value;
9597
+ throw new Error("Role evodev.runtime must be codex or claude.");
9598
+ }
9190
9599
  function parseWriteMode(value, fallback) {
9191
9600
  if (value === undefined || value === null)
9192
9601
  return fallback;
@@ -9195,6 +9604,20 @@ function parseWriteMode(value, fallback) {
9195
9604
  }
9196
9605
  throw new Error("Role writeMode is invalid.");
9197
9606
  }
9607
+ function optionalWriteMode(value) {
9608
+ if (value === undefined || value === null)
9609
+ return null;
9610
+ return parseWriteMode(value, "repo-write");
9611
+ }
9612
+ function parseStringList(value) {
9613
+ if (value === undefined || value === null)
9614
+ return [];
9615
+ if (typeof value === "string" && value.trim() !== "")
9616
+ return [value.trim()];
9617
+ if (!Array.isArray(value))
9618
+ return [];
9619
+ return value.filter((item) => typeof item === "string" && item.trim() !== "");
9620
+ }
9198
9621
  function isActiveTeamAgentStatus(status) {
9199
9622
  return status === "starting" || status === "running" || status === "busy" || status === "idle" || status === "waiting-input" || status === "recovering" || status === "recreated";
9200
9623
  }
@@ -9933,7 +10356,7 @@ async function handleUserPromptSubmit(input) {
9933
10356
  const previousBinding = await readSessionBinding(input.homeDir, input.rawPayload);
9934
10357
  const teamRuntimeContext = previousBinding?.teamRuntimeContextDeliveredAt === undefined || previousBinding.teamRuntimeContextDeliveredAt === null ? await createTeamRuntimeContextForUserPrompt(input) : null;
9935
10358
  const shouldShowDiagnostics = input.teamRuntimeDisplayMode === "development";
9936
- const teamRuntimeContextDeliveredAt = teamRuntimeContext !== null && shouldShowDiagnostics ? input.receivedAt ?? new Date().toISOString() : previousBinding?.teamRuntimeContextDeliveredAt ?? null;
10359
+ const teamRuntimeContextDeliveredAt = teamRuntimeContext !== null ? input.receivedAt ?? new Date().toISOString() : previousBinding?.teamRuntimeContextDeliveredAt ?? null;
9937
10360
  const binding = {
9938
10361
  version: 1,
9939
10362
  target: input.target,
@@ -9955,7 +10378,7 @@ async function handleUserPromptSubmit(input) {
9955
10378
  let output = visibleContext === null || !shouldShowDiagnostics ? null : hookOutput(input.event.type, {
9956
10379
  additionalContext: visibleContext
9957
10380
  });
9958
- if (teamRuntimeContext !== null && shouldShowDiagnostics) {
10381
+ if (teamRuntimeContext !== null) {
9959
10382
  output = appendAdditionalContext(output, input.event.type, teamRuntimeContext);
9960
10383
  }
9961
10384
  return createRuntimeResult(input, output, {
@@ -11250,14 +11673,14 @@ async function runDaemonForeground(input) {
11250
11673
  }));
11251
11674
  }
11252
11675
  });
11253
- await new Promise((resolve4, reject) => {
11676
+ await new Promise((resolve5, reject) => {
11254
11677
  const onError = (error) => {
11255
11678
  server.off("listening", onListening);
11256
11679
  reject(error);
11257
11680
  };
11258
11681
  const onListening = () => {
11259
11682
  server.off("error", onError);
11260
- resolve4();
11683
+ resolve5();
11261
11684
  };
11262
11685
  server.once("error", onError);
11263
11686
  server.once("listening", onListening);
@@ -11274,11 +11697,11 @@ async function runDaemonForeground(input) {
11274
11697
  processEvolutionTriggers({ homeDir: input.homeDir, limit: 20 }).then(() => clearDaemonEvolutionProcessError(input.homeDir)).catch((error) => recordDaemonEvolutionProcessError(input.homeDir, error));
11275
11698
  }, 5000);
11276
11699
  evolutionInterval.unref();
11277
- await new Promise((resolve4, reject) => {
11700
+ await new Promise((resolve5, reject) => {
11278
11701
  server.once("close", () => {
11279
11702
  clearInterval(reconcileInterval);
11280
11703
  clearInterval(evolutionInterval);
11281
- resolve4();
11704
+ resolve5();
11282
11705
  });
11283
11706
  server.once("error", reject);
11284
11707
  });
@@ -12214,7 +12637,7 @@ function isRecord10(value) {
12214
12637
  }
12215
12638
  // packages/core/src/pack/index.ts
12216
12639
  import { readFile as readFile14, readdir as readdir8, stat as stat10 } from "node:fs/promises";
12217
- import { isAbsolute as isAbsolute5, join as join12, relative as relative6, sep } from "node:path";
12640
+ import { isAbsolute as isAbsolute6, join as join12, relative as relative7, sep } from "node:path";
12218
12641
 
12219
12642
  // packages/core/src/protected-zones/index.ts
12220
12643
  var SENSITIVE_DIRECTORY_SEGMENTS = new Set([
@@ -12698,7 +13121,7 @@ async function collectPackRelativePaths(packRoot, dir = packRoot) {
12698
13121
  const paths = [];
12699
13122
  for (const entry of entries) {
12700
13123
  const absolutePath = join12(dir, entry.name);
12701
- const relativePath = normalizeRelativePath(relative6(packRoot, absolutePath));
13124
+ const relativePath = normalizeRelativePath(relative7(packRoot, absolutePath));
12702
13125
  paths.push(relativePath);
12703
13126
  if (entry.isDirectory()) {
12704
13127
  paths.push(...await collectPackRelativePaths(packRoot, absolutePath));
@@ -12713,7 +13136,7 @@ function validatePackRelativePath(path, packRoot) {
12713
13136
  if (path.includes("\x00")) {
12714
13137
  return { severity: "error", code: "path-invalid", message: "Path must not contain NUL bytes." };
12715
13138
  }
12716
- if (isAbsolute5(path) || path.startsWith("~")) {
13139
+ if (isAbsolute6(path) || path.startsWith("~")) {
12717
13140
  return {
12718
13141
  severity: "error",
12719
13142
  code: "path-absolute",
@@ -12729,8 +13152,8 @@ function validatePackRelativePath(path, packRoot) {
12729
13152
  };
12730
13153
  }
12731
13154
  const absolute = join12(packRoot, normalized);
12732
- const rel = relative6(packRoot, absolute);
12733
- if (rel === "" || rel.startsWith("..") || isAbsolute5(rel)) {
13155
+ const rel = relative7(packRoot, absolute);
13156
+ if (rel === "" || rel.startsWith("..") || isAbsolute6(rel)) {
12734
13157
  return {
12735
13158
  severity: "error",
12736
13159
  code: "path-traversal",
@@ -13145,7 +13568,7 @@ function getEnabledPluginIds(settings) {
13145
13568
  }
13146
13569
  // packages/core/src/project/index.ts
13147
13570
  import { mkdir as mkdir13, readFile as readFile16, readdir as readdir9, stat as stat11, writeFile as writeFile12 } from "node:fs/promises";
13148
- import { basename as basename5, join as join14, relative as relative7 } from "node:path";
13571
+ import { basename as basename5, join as join14, relative as relative8 } from "node:path";
13149
13572
  var PROJECT_CONTEXT_ALLOWED_RELATIVE_PATHS = [
13150
13573
  ".evodev/project.json",
13151
13574
  ".evodev/profile.md",
@@ -13352,7 +13775,7 @@ async function collectProjectFileMetadata(projectDir) {
13352
13775
  const entries = await readdir9(dir, { withFileTypes: true });
13353
13776
  for (const entry of entries) {
13354
13777
  const absolutePath = join14(dir, entry.name);
13355
- const relativePath = relative7(projectDir, absolutePath).replaceAll("\\", "/");
13778
+ const relativePath = relative8(projectDir, absolutePath).replaceAll("\\", "/");
13356
13779
  if (shouldExcludePath(relativePath, entry.isDirectory())) {
13357
13780
  continue;
13358
13781
  }
@@ -14125,6 +14548,8 @@ export {
14125
14548
  resolveTraceSessionKey,
14126
14549
  resolveTeamRunPaths,
14127
14550
  resolveTeamRole,
14551
+ resolveTeamOverlay,
14552
+ resolveTeamAgentReference,
14128
14553
  resolveTaskContractOutputPath,
14129
14554
  resolveProjectLogKey,
14130
14555
  resolveOkfKnowledgePaths,
@@ -14140,10 +14565,14 @@ export {
14140
14565
  resolveContextInjectionReceiptPath,
14141
14566
  resolveCodexCapabilityArtifactPath,
14142
14567
  resolveCodeAgentTraceRefPaths,
14568
+ renderRoleAgentDefinitionContext,
14569
+ renderMainTeamOverlayContext,
14143
14570
  recordTeamAgentNativeSession,
14144
14571
  recordCodeAgentTraceRefFromHook,
14145
14572
  reconcileTeamRun,
14146
14573
  rebuildOkfKnowledgeIndexes,
14574
+ readTeamAgentSummary,
14575
+ readTeamAgentDefinition,
14147
14576
  readTaskContract,
14148
14577
  readRuntimeInjectionSettings,
14149
14578
  readPendingTeamMessagesForRole,
@@ -14168,6 +14597,7 @@ export {
14168
14597
  pathExists8 as pathExists,
14169
14598
  parseWorkflowManifest,
14170
14599
  parseTeamRoleDefinition,
14600
+ parseTeamDefinitionMarkdown,
14171
14601
  parseSyncState,
14172
14602
  parseSkillManifest,
14173
14603
  parseSettings,
@@ -14250,6 +14680,7 @@ export {
14250
14680
  formatAgentComposeDryRun,
14251
14681
  findCandidateConflictOrDuplicate,
14252
14682
  ensureOkfKnowledgeBase,
14683
+ ensureDefaultTeamOverlay,
14253
14684
  enqueueEvolutionTrigger,
14254
14685
  dryRunObservabilityRetentionCleanup,
14255
14686
  discardFailedOkfKnowledgePlan,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evo-dev/core",
3
- "version": "0.0.1-alpha.2",
3
+ "version": "0.0.1-alpha.3",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -790,7 +790,7 @@ async function handleUserPromptSubmit(input: HandleHookRuntimeInput): Promise<Ho
790
790
  : null;
791
791
  const shouldShowDiagnostics = input.teamRuntimeDisplayMode === "development";
792
792
  const teamRuntimeContextDeliveredAt =
793
- teamRuntimeContext !== null && shouldShowDiagnostics
793
+ teamRuntimeContext !== null
794
794
  ? (input.receivedAt ?? new Date().toISOString())
795
795
  : (previousBinding?.teamRuntimeContextDeliveredAt ?? null);
796
796
  const binding: HookRuntimeSessionBinding = {
@@ -819,7 +819,7 @@ async function handleUserPromptSubmit(input: HandleHookRuntimeInput): Promise<Ho
819
819
  : hookOutput(input.event.type, {
820
820
  additionalContext: visibleContext,
821
821
  });
822
- if (teamRuntimeContext !== null && shouldShowDiagnostics) {
822
+ if (teamRuntimeContext !== null) {
823
823
  output = appendAdditionalContext(output, input.event.type, teamRuntimeContext);
824
824
  }
825
825