@jmanuelcorral/openteam 0.12.0 → 0.13.1

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
@@ -293,7 +293,7 @@ var GraphEngineSchema = z2.enum(["builtin", "langgraph"]);
293
293
  var DEFAULT_GRAPH_JOURNAL_ROOT = ".opencode/openteam-local/graph/runs";
294
294
  var DEFAULT_GRAPH_WORKTREES_DIR = ".opencode/openteam-local/graph/worktrees";
295
295
  var GraphConfigSchema = z2.object({
296
- mode: GraphModeSchema.default("off"),
296
+ mode: GraphModeSchema.default("shadow"),
297
297
  engine: GraphEngineSchema.optional(),
298
298
  killSwitch: z2.boolean().default(false),
299
299
  journalRoot: z2.string().min(1).default(DEFAULT_GRAPH_JOURNAL_ROOT),
@@ -316,8 +316,8 @@ var ConsoleConfigSchema = z2.object({
316
316
  pty: z2.boolean().optional()
317
317
  }).strict().default({ enabled: true }),
318
318
  graphView: z2.object({
319
- enabled: z2.boolean().default(false)
320
- }).strict().optional()
319
+ enabled: z2.boolean().default(true)
320
+ }).strict().default({ enabled: true })
321
321
  }).strict().default({
322
322
  host: "127.0.0.1",
323
323
  port: 4599,
@@ -326,7 +326,8 @@ var ConsoleConfigSchema = z2.object({
326
326
  recentRoutes: 50,
327
327
  openBrowser: false,
328
328
  remoteStorage: false,
329
- terminal: { enabled: true }
329
+ terminal: { enabled: true },
330
+ graphView: { enabled: true }
330
331
  });
331
332
  var DEFAULT_STORAGE_SQLITE_INDEX_PATH = ".opencode/openteam-local/index.sqlite";
332
333
  var StorageConfigSchema = z2.object({
@@ -505,7 +506,13 @@ var OpenTeamConfigObjectSchema = z2.object({
505
506
  console: ConsoleConfigSchema,
506
507
  storage: StorageConfigSchema,
507
508
  memory: MemoryConfigSchema.optional(),
508
- graph: GraphConfigSchema.optional(),
509
+ graph: GraphConfigSchema.default({
510
+ mode: "shadow",
511
+ killSwitch: false,
512
+ journalRoot: DEFAULT_GRAPH_JOURNAL_ROOT,
513
+ operatorApproval: false,
514
+ worktrees: { enabled: false }
515
+ }),
509
516
  orchestrator: OrchestratorConfigSchema.optional()
510
517
  }).strict();
511
518
  var OpenTeamConfigSchema = OpenTeamConfigObjectSchema;
@@ -2855,7 +2862,7 @@ function loadOpenTeamConfig(raw) {
2855
2862
 
2856
2863
  // src/config/resolve.ts
2857
2864
  function resolveGraphConfig(config, source) {
2858
- const configuredMode = config.graph?.mode ?? "off";
2865
+ const configuredMode = config.graph?.mode ?? "shadow";
2859
2866
  const killSwitch = config.graph?.killSwitch ?? false;
2860
2867
  const effectiveMode = killSwitch ? "off" : configuredMode;
2861
2868
  return {
@@ -8134,6 +8141,20 @@ function rosterHealthSection(audit, loadError, rosterRoleCount) {
8134
8141
  }
8135
8142
  return lines;
8136
8143
  }
8144
+ function gitignoreSection(gitignore) {
8145
+ if (gitignore.missingRules.length === 0) {
8146
+ return [
8147
+ " gitignore:",
8148
+ ` ✓ ${gitignore.path} ignores openteam's generated runtime state.`
8149
+ ];
8150
+ }
8151
+ const quoted = gitignore.missingRules.map((rule) => `\`${rule}\``).join(", ");
8152
+ const lines = [" gitignore:"];
8153
+ lines.push(gitignore.exists ? ` ✗ ${gitignore.path} is missing openteam ignore rule(s): ${gitignore.missingRules.join(", ")}` : ` ✗ ${gitignore.path} does not exist, so no openteam ignore rule(s) are in place: ${gitignore.missingRules.join(", ")}`);
8154
+ lines.push(" problem: openteam writes machine-local runtime output (telemetry, graph state, soak recordings) that must not be committed.");
8155
+ lines.push(` remedy: add ${quoted} to ${gitignore.path} (or re-run \`openteam setup\`), then re-run \`openteam doctor\`.`);
8156
+ return lines;
8157
+ }
8137
8158
  function agentModelsSection(diagnostics, searchedPaths) {
8138
8159
  const lines = [" agent models:"];
8139
8160
  if (diagnostics.length === 0) {
@@ -8181,6 +8202,9 @@ function renderDoctor(input) {
8181
8202
  lines.push(...diagnosticsSection(input.diagnostics));
8182
8203
  }
8183
8204
  lines.push(...rosterHealthSection(input.rosterAudit, input.rosterLoadError, input.rosterRoleCount));
8205
+ if (input.gitignore !== undefined) {
8206
+ lines.push(...gitignoreSection(input.gitignore));
8207
+ }
8184
8208
  if (input.otelBackend !== undefined) {
8185
8209
  const otel = input.otelBackend;
8186
8210
  lines.push(" opentelemetry:");
@@ -8446,6 +8470,143 @@ function renderMigration(report) {
8446
8470
  // src/commands/purge.ts
8447
8471
  import * as path3 from "node:path";
8448
8472
 
8473
+ // src/storage/graph/soakRecorder.ts
8474
+ var SOAK_EVIDENCE_DIR = ".opencode/soak";
8475
+ var SOAK_RECORDER_BASE_DIR = ".opencode";
8476
+ var SOAK_RECORDER_ID_FILENAME = "soak-recorder-id";
8477
+ var SOAK_RECORDER_ID_PATH = `${SOAK_RECORDER_BASE_DIR}/${SOAK_RECORDER_ID_FILENAME}`;
8478
+ async function ensureRecorderId(ports, basePath) {
8479
+ const idPath = `${basePath}/${SOAK_RECORDER_ID_FILENAME}`;
8480
+ if (await ports.fs.exists(idPath)) {
8481
+ const id = (await ports.fs.readFile(idPath)).trim();
8482
+ if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id)) {
8483
+ return id;
8484
+ }
8485
+ }
8486
+ const newId = ports.id.randomUUID();
8487
+ await ports.fs.writeFile(idPath, newId);
8488
+ return newId;
8489
+ }
8490
+ async function readAllChains(ports, evidenceDir) {
8491
+ if (!await ports.fs.exists(evidenceDir)) {
8492
+ return { chains: [], rejectedLines: 0, rejections: [] };
8493
+ }
8494
+ const files = await ports.fs.readDir(evidenceDir);
8495
+ const chains = [];
8496
+ const rejections = [];
8497
+ for (const file of files) {
8498
+ if (!file.endsWith(".jsonl")) {
8499
+ continue;
8500
+ }
8501
+ const content = await ports.fs.readFile(`${evidenceDir}/${file}`);
8502
+ const lines = content.split(`
8503
+ `);
8504
+ const observations = [];
8505
+ for (const [index, line] of lines.entries()) {
8506
+ if (line.trim().length === 0) {
8507
+ continue;
8508
+ }
8509
+ const lineNumber = index + 1;
8510
+ let rawParsed;
8511
+ try {
8512
+ rawParsed = JSON.parse(line);
8513
+ } catch {
8514
+ rejections.push({ file, lineNumber, detail: "invalid JSON" });
8515
+ continue;
8516
+ }
8517
+ const parsed = SoakObservationSchema.safeParse(rawParsed);
8518
+ if (parsed.success) {
8519
+ observations.push(parsed.data);
8520
+ } else {
8521
+ rejections.push({
8522
+ file,
8523
+ lineNumber,
8524
+ detail: formatSoakObservationIssues(parsed.error.issues)
8525
+ });
8526
+ }
8527
+ }
8528
+ if (observations.length > 0) {
8529
+ chains.push(observations);
8530
+ }
8531
+ }
8532
+ return { chains, rejectedLines: rejections.length, rejections };
8533
+ }
8534
+ function formatSoakObservationIssues(issues) {
8535
+ return issues.map((i) => `${i.path.join(".")}: ${i.code}`).join("; ");
8536
+ }
8537
+ function canonicalObservationPreimage2(obs) {
8538
+ return JSON.stringify({
8539
+ version: obs.version,
8540
+ seq: obs.seq,
8541
+ timestamp: obs.timestamp,
8542
+ platform: obs.platform,
8543
+ opencodeVersion: obs.opencodeVersion,
8544
+ provenance: obs.provenance,
8545
+ traceDigest: obs.traceDigest,
8546
+ criticalDivergences: obs.criticalDivergences,
8547
+ privacy: obs.privacy,
8548
+ duplicateEffects: obs.duplicateEffects,
8549
+ modelVerification: obs.modelVerification
8550
+ });
8551
+ }
8552
+ async function appendObservation(ports, evidenceDir, recorderId, input) {
8553
+ if (input.opencodeVersion === "unknown") {
8554
+ throw new Error("opencode-version-unreadable");
8555
+ }
8556
+ await ports.fs.mkdir(evidenceDir);
8557
+ const chainPath = `${evidenceDir}/${recorderId}.jsonl`;
8558
+ let seq = 0;
8559
+ let prevChainDigest = "0".repeat(64);
8560
+ if (await ports.fs.exists(chainPath)) {
8561
+ const content = await ports.fs.readFile(chainPath);
8562
+ const lines = content.split(`
8563
+ `).filter((l) => l.trim().length > 0);
8564
+ if (lines.length > 0) {
8565
+ const lastLine = lines[lines.length - 1];
8566
+ let rawParsed;
8567
+ try {
8568
+ rawParsed = JSON.parse(lastLine);
8569
+ } catch {
8570
+ throw new Error("corrupt chain tail: invalid JSON");
8571
+ }
8572
+ const parsed = SoakObservationSchema.safeParse(rawParsed);
8573
+ if (!parsed.success) {
8574
+ const detail = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.code}`).join("; ");
8575
+ throw new Error(`corrupt chain tail: ${detail}`);
8576
+ }
8577
+ seq = parsed.data.seq + 1;
8578
+ prevChainDigest = parsed.data.chainDigest;
8579
+ }
8580
+ }
8581
+ const timestamp = ports.clock.now();
8582
+ const base = {
8583
+ version: 1,
8584
+ seq,
8585
+ timestamp,
8586
+ platform: input.platform,
8587
+ opencodeVersion: input.opencodeVersion,
8588
+ provenance: input.provenance,
8589
+ traceDigest: input.traceDigest,
8590
+ criticalDivergences: input.criticalDivergences,
8591
+ privacy: input.privacy,
8592
+ duplicateEffects: input.duplicateEffects,
8593
+ modelVerification: input.modelVerification
8594
+ };
8595
+ const preimage = canonicalObservationPreimage2(base);
8596
+ const chainDigest = sha256Hex(prevChainDigest + preimage);
8597
+ const observation = { ...base, chainDigest };
8598
+ assertReferenceOnly(observation);
8599
+ const line = JSON.stringify(observation);
8600
+ if (await ports.fs.exists(chainPath)) {
8601
+ const existing = await ports.fs.readFile(chainPath);
8602
+ await ports.fs.writeFile(chainPath, `${existing}
8603
+ ${line}`);
8604
+ } else {
8605
+ await ports.fs.writeFile(chainPath, line);
8606
+ }
8607
+ return observation;
8608
+ }
8609
+
8449
8610
  // src/commands/setup.ts
8450
8611
  var OPENTEAM_PLUGIN_SPEC = "@jmanuelcorral/openteam";
8451
8612
  var OPENCODE_GITIGNORE_PATH = ".opencode/.gitignore";
@@ -8457,6 +8618,11 @@ var GENERATED_OPENTEAM_STATE_PATHS = [
8457
8618
  DEFAULT_STORAGE_SQLITE_INDEX_PATH,
8458
8619
  DEFAULT_MEMORY_INDEX_PATH
8459
8620
  ];
8621
+ var GENERATED_OPENTEAM_STATE_GROUPS = [
8622
+ { kind: "dir", paths: GENERATED_OPENTEAM_STATE_PATHS },
8623
+ { kind: "dir", paths: [SOAK_EVIDENCE_DIR] },
8624
+ { kind: "file", paths: [SOAK_RECORDER_ID_PATH] }
8625
+ ];
8460
8626
  var OPENCODE_DIR = ".opencode";
8461
8627
  var AGENT_DIR = `${OPENCODE_DIR}/agent`;
8462
8628
  function splitSetupPath(path3) {
@@ -8477,18 +8643,27 @@ function commonGeneratedStateRoot(paths) {
8477
8643
  }
8478
8644
  return common.join("/");
8479
8645
  }
8480
- function generatedStateIgnoreRule() {
8481
- const root = commonGeneratedStateRoot(GENERATED_OPENTEAM_STATE_PATHS);
8646
+ function generatedStateIgnoreRule(group) {
8647
+ const root = commonGeneratedStateRoot(group.paths);
8482
8648
  const opencodePrefix = `${OPENCODE_DIR}/`;
8483
8649
  if (!root.startsWith(opencodePrefix)) {
8484
8650
  throw new Error(`generated openteam state path is outside ${OPENCODE_DIR}`);
8485
8651
  }
8486
- return `${root.slice(opencodePrefix.length)}/`;
8652
+ const rule = root.slice(opencodePrefix.length);
8653
+ return group.kind === "dir" ? `${rule}/` : rule;
8487
8654
  }
8488
- var OPENCODE_GITIGNORE_GENERATED_STATE_RULES = [
8489
- generatedStateIgnoreRule()
8490
- ];
8655
+ var OPENCODE_GITIGNORE_GENERATED_STATE_RULES = GENERATED_OPENTEAM_STATE_GROUPS.map(generatedStateIgnoreRule);
8491
8656
  var LEGACY_OPENCODE_GITIGNORE_STATE_RULES = ["openteam/"];
8657
+ function normalizeGitignoreRule(line) {
8658
+ return line.trim().replace(/^\/+/, "");
8659
+ }
8660
+ function activeGitignoreRules(gitignore) {
8661
+ return gitignore.split(/\r?\n/).map(normalizeGitignoreRule).filter((line) => line.length > 0 && !line.startsWith("#"));
8662
+ }
8663
+ function missingGeneratedStateRules(gitignore) {
8664
+ const present = new Set(activeGitignoreRules(gitignore));
8665
+ return OPENCODE_GITIGNORE_GENERATED_STATE_RULES.filter((rule) => !present.has(rule));
8666
+ }
8492
8667
 
8493
8668
  // src/commands/purge.ts
8494
8669
  var PURGE_CATEGORY_IDS = [
@@ -8536,7 +8711,7 @@ function resolveStaticPurgeItems(config, paths) {
8536
8711
  ...paths.opencodeConfigPaths.map((p) => ({ kind: "opencode-config", path: p })),
8537
8712
  { kind: "gitignore", path: paths.gitignorePath }
8538
8713
  ],
8539
- roster: [],
8714
+ roster: [{ kind: "file", path: OPENTEAM_ROSTER_PATH }],
8540
8715
  decisions: [
8541
8716
  { kind: "file", path: paths.decisionsPath },
8542
8717
  { kind: "file", path: paths.telemetryPath }
@@ -8828,8 +9003,12 @@ function categoryPrompt(id, items) {
8828
9003
  return "Remove openteam configuration and wiring?";
8829
9004
  case "roster": {
8830
9005
  const names = items.filter((item) => item.kind === "agent").map((item) => item.name);
8831
- const listed = names.join(", ");
8832
- return `Remove the agent roster? (${names.length} user agent${names.length === 1 ? "" : "s"}: ${listed})`;
9006
+ const hasRegistry = items.some((item) => item.kind === "file" && item.path === OPENTEAM_ROSTER_PATH);
9007
+ const plural = names.length === 1 ? "" : "s";
9008
+ const agentNames = names.length > 0 ? `: ${names.join(", ")}` : "";
9009
+ const agentClause = `${names.length} user agent${plural}${agentNames}`;
9010
+ const parts = hasRegistry ? [`roster registry (${OPENTEAM_ROSTER_PATH})`, agentClause] : [agentClause];
9011
+ return `Remove the agent roster? (${parts.join("; ")})`;
8833
9012
  }
8834
9013
  case "decisions":
8835
9014
  return "Remove decisions and telemetry?";
@@ -8891,7 +9070,9 @@ async function collectCategories(input) {
8891
9070
  const { runtime, config, paths } = input;
8892
9071
  const staticItems = resolveStaticPurgeItems(config, paths);
8893
9072
  const agents = await runtime.port.listAgents();
8894
- const rosterItems = agents.filter((agent) => path3.resolve(agent.path) !== path3.resolve(paths.orchestratorAgentPath)).map((agent) => ({ kind: "agent", path: agent.path, name: agent.name }));
9073
+ const discoveredAgents = agents.filter((agent) => path3.resolve(agent.path) !== path3.resolve(paths.orchestratorAgentPath)).map((agent) => ({ kind: "agent", path: agent.path, name: agent.name }));
9074
+ const rosterRegistry = await presentItemsFor(runtime.port, staticItems.roster);
9075
+ const rosterItems = [...rosterRegistry, ...discoveredAgents];
8895
9076
  const worktrees = await runtime.port.listWorktrees();
8896
9077
  const worktreeItems = worktrees.map((worktree) => ({
8897
9078
  kind: "worktree",
@@ -10044,6 +10225,15 @@ async function runCli(argv, deps) {
10044
10225
  ...defaultModel !== undefined ? { defaultModel } : {}
10045
10226
  });
10046
10227
  const legacyLayout = deps.detectLegacyLayout !== undefined ? await deps.detectLegacyLayout() : undefined;
10228
+ let gitignoreCoverage;
10229
+ if (deps.readGitignore !== undefined) {
10230
+ const raw = await deps.readGitignore();
10231
+ gitignoreCoverage = {
10232
+ path: OPENCODE_GITIGNORE_PATH,
10233
+ exists: raw !== undefined,
10234
+ missingRules: missingGeneratedStateRules(raw ?? "")
10235
+ };
10236
+ }
10047
10237
  const otelBackend = describeOtelBackendForDoctor({
10048
10238
  backend: "opentelemetry",
10049
10239
  connectionEnv: "APPLICATIONINSIGHTS_CONNECTION_STRING"
@@ -10076,7 +10266,8 @@ async function runCli(argv, deps) {
10076
10266
  ...opencodeConfigError !== undefined ? { opencodeConfigError } : {},
10077
10267
  ...cacheEntries !== undefined ? { cacheEntries, cliVersion: deps.version } : {},
10078
10268
  ...legacyLayout !== undefined && legacyLayout.length > 0 ? { legacyLayout } : {},
10079
- ...otelBackend !== undefined ? { otelBackend } : {}
10269
+ ...otelBackend !== undefined ? { otelBackend } : {},
10270
+ ...gitignoreCoverage !== undefined ? { gitignore: gitignoreCoverage } : {}
10080
10271
  })
10081
10272
  };
10082
10273
  }
@@ -10752,139 +10943,6 @@ function compareShadowRun(legacy, shadow) {
10752
10943
  };
10753
10944
  }
10754
10945
 
10755
- // src/storage/graph/soakRecorder.ts
10756
- async function ensureRecorderId(ports, basePath) {
10757
- const idPath = `${basePath}/soak-recorder-id`;
10758
- if (await ports.fs.exists(idPath)) {
10759
- const id = (await ports.fs.readFile(idPath)).trim();
10760
- if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id)) {
10761
- return id;
10762
- }
10763
- }
10764
- const newId = ports.id.randomUUID();
10765
- await ports.fs.writeFile(idPath, newId);
10766
- return newId;
10767
- }
10768
- async function readAllChains(ports, evidenceDir) {
10769
- if (!await ports.fs.exists(evidenceDir)) {
10770
- return { chains: [], rejectedLines: 0, rejections: [] };
10771
- }
10772
- const files = await ports.fs.readDir(evidenceDir);
10773
- const chains = [];
10774
- const rejections = [];
10775
- for (const file of files) {
10776
- if (!file.endsWith(".jsonl")) {
10777
- continue;
10778
- }
10779
- const content = await ports.fs.readFile(`${evidenceDir}/${file}`);
10780
- const lines = content.split(`
10781
- `);
10782
- const observations = [];
10783
- for (const [index, line] of lines.entries()) {
10784
- if (line.trim().length === 0) {
10785
- continue;
10786
- }
10787
- const lineNumber = index + 1;
10788
- let rawParsed;
10789
- try {
10790
- rawParsed = JSON.parse(line);
10791
- } catch {
10792
- rejections.push({ file, lineNumber, detail: "invalid JSON" });
10793
- continue;
10794
- }
10795
- const parsed = SoakObservationSchema.safeParse(rawParsed);
10796
- if (parsed.success) {
10797
- observations.push(parsed.data);
10798
- } else {
10799
- rejections.push({
10800
- file,
10801
- lineNumber,
10802
- detail: formatSoakObservationIssues(parsed.error.issues)
10803
- });
10804
- }
10805
- }
10806
- if (observations.length > 0) {
10807
- chains.push(observations);
10808
- }
10809
- }
10810
- return { chains, rejectedLines: rejections.length, rejections };
10811
- }
10812
- function formatSoakObservationIssues(issues) {
10813
- return issues.map((i) => `${i.path.join(".")}: ${i.code}`).join("; ");
10814
- }
10815
- function canonicalObservationPreimage2(obs) {
10816
- return JSON.stringify({
10817
- version: obs.version,
10818
- seq: obs.seq,
10819
- timestamp: obs.timestamp,
10820
- platform: obs.platform,
10821
- opencodeVersion: obs.opencodeVersion,
10822
- provenance: obs.provenance,
10823
- traceDigest: obs.traceDigest,
10824
- criticalDivergences: obs.criticalDivergences,
10825
- privacy: obs.privacy,
10826
- duplicateEffects: obs.duplicateEffects,
10827
- modelVerification: obs.modelVerification
10828
- });
10829
- }
10830
- async function appendObservation(ports, evidenceDir, recorderId, input) {
10831
- if (input.opencodeVersion === "unknown") {
10832
- throw new Error("opencode-version-unreadable");
10833
- }
10834
- await ports.fs.mkdir(evidenceDir);
10835
- const chainPath = `${evidenceDir}/${recorderId}.jsonl`;
10836
- let seq = 0;
10837
- let prevChainDigest = "0".repeat(64);
10838
- if (await ports.fs.exists(chainPath)) {
10839
- const content = await ports.fs.readFile(chainPath);
10840
- const lines = content.split(`
10841
- `).filter((l) => l.trim().length > 0);
10842
- if (lines.length > 0) {
10843
- const lastLine = lines[lines.length - 1];
10844
- let rawParsed;
10845
- try {
10846
- rawParsed = JSON.parse(lastLine);
10847
- } catch {
10848
- throw new Error("corrupt chain tail: invalid JSON");
10849
- }
10850
- const parsed = SoakObservationSchema.safeParse(rawParsed);
10851
- if (!parsed.success) {
10852
- const detail = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.code}`).join("; ");
10853
- throw new Error(`corrupt chain tail: ${detail}`);
10854
- }
10855
- seq = parsed.data.seq + 1;
10856
- prevChainDigest = parsed.data.chainDigest;
10857
- }
10858
- }
10859
- const timestamp = ports.clock.now();
10860
- const base = {
10861
- version: 1,
10862
- seq,
10863
- timestamp,
10864
- platform: input.platform,
10865
- opencodeVersion: input.opencodeVersion,
10866
- provenance: input.provenance,
10867
- traceDigest: input.traceDigest,
10868
- criticalDivergences: input.criticalDivergences,
10869
- privacy: input.privacy,
10870
- duplicateEffects: input.duplicateEffects,
10871
- modelVerification: input.modelVerification
10872
- };
10873
- const preimage = canonicalObservationPreimage2(base);
10874
- const chainDigest = sha256Hex(prevChainDigest + preimage);
10875
- const observation = { ...base, chainDigest };
10876
- assertReferenceOnly(observation);
10877
- const line = JSON.stringify(observation);
10878
- if (await ports.fs.exists(chainPath)) {
10879
- const existing = await ports.fs.readFile(chainPath);
10880
- await ports.fs.writeFile(chainPath, `${existing}
10881
- ${line}`);
10882
- } else {
10883
- await ports.fs.writeFile(chainPath, line);
10884
- }
10885
- return observation;
10886
- }
10887
-
10888
10946
  // src/plugin/soakObserver.ts
10889
10947
  function resolvePlatform(platform) {
10890
10948
  if (platform === "win32")
@@ -13029,7 +13087,7 @@ var createOtlpSpanExporter = (connection, config) => {
13029
13087
  // package.json
13030
13088
  var package_default = {
13031
13089
  name: "@jmanuelcorral/openteam",
13032
- version: "0.12.0",
13090
+ version: "0.13.1",
13033
13091
  packageManager: "bun@1.3.14",
13034
13092
  description: "Cost-aware, local-first routing plugin for opencode with cheapest-capable frontier fallback and multi-agent orchestration.",
13035
13093
  license: "MIT",
@@ -13205,7 +13263,6 @@ function warnSoakEvidenceRejections(result, warn) {
13205
13263
  var SHADOW_CERT_PATH = "artifacts/graph-shadow-certificate.json";
13206
13264
  var RELEASE_CERT_PATH = "artifacts/graph-release-certificate.json";
13207
13265
  var SOAK_CERT_PATH = "artifacts/graph-soak-certificate.json";
13208
- var SOAK_EVIDENCE_DIR = ".opencode/soak";
13209
13266
  async function readAndParseCertificate(storage, path4, parse2, digestExtractor) {
13210
13267
  try {
13211
13268
  const content = await storage.read(path4);
@@ -13728,14 +13785,14 @@ var server = async (ctx, rawOptions) => {
13728
13785
  let shadowDeps;
13729
13786
  if (graphConfig.effectiveMode !== "off") {
13730
13787
  const recorderPorts = recorderPortsFromStorage(storage);
13731
- const recorderId = await ensureRecorderId(recorderPorts, ".opencode");
13788
+ const recorderId = await ensureRecorderId(recorderPorts, SOAK_RECORDER_BASE_DIR);
13732
13789
  shadowDeps = {
13733
13790
  gate: {
13734
13791
  mode: graphConfig.configuredMode,
13735
13792
  killSwitch: graphConfig.killSwitch
13736
13793
  },
13737
13794
  ports: recorderPorts,
13738
- evidenceDir: ".opencode/soak",
13795
+ evidenceDir: SOAK_EVIDENCE_DIR,
13739
13796
  recorderId,
13740
13797
  resolveOpencodeVersion: getOpencodeVersion,
13741
13798
  criticalCodes: DEFAULT_SOAK_POLICY.criticalDivergenceCodes
@@ -31,6 +31,25 @@ export type RecorderPorts = {
31
31
  export type SoakChainReadPorts = {
32
32
  readonly fs: Pick<FsPort, "readFile" | "exists" | "readDir">;
33
33
  };
34
+ /**
35
+ * Directory (relative to cwd) the shadow soak pipeline writes its JSONL evidence
36
+ * chains to. Exported so `openteam setup`'s ignore-rule derivation and the plugin
37
+ * writer in `src/index.ts` share one literal and can never drift apart (the drift
38
+ * that left these recordings unignored in consuming projects).
39
+ */
40
+ export declare const SOAK_EVIDENCE_DIR = ".opencode/soak";
41
+ /**
42
+ * Base directory that holds the machine-local recorder id file. Passed to
43
+ * {@link ensureRecorderId} as `basePath`.
44
+ */
45
+ export declare const SOAK_RECORDER_BASE_DIR = ".opencode";
46
+ /** Filename of the machine-local recorder id, stored under {@link SOAK_RECORDER_BASE_DIR}. */
47
+ export declare const SOAK_RECORDER_ID_FILENAME = "soak-recorder-id";
48
+ /**
49
+ * Full path (relative to cwd) of the machine-local recorder id file. Exported so
50
+ * the ignore-rule derivation covers it alongside {@link SOAK_EVIDENCE_DIR}.
51
+ */
52
+ export declare const SOAK_RECORDER_ID_PATH = ".opencode/soak-recorder-id";
34
53
  export type SoakObservationLineRejection = {
35
54
  readonly file: string;
36
55
  readonly lineNumber: number;
@@ -1 +1 @@
1
- {"version":3,"file":"soakRecorder.d.ts","sourceRoot":"","sources":["../../../src/storage/graph/soakRecorder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"soakRecorder.d.ts","sourceRoot":"","sources":["../../../src/storage/graph/soakRecorder.ts"],"names":[],"mappings":"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"}
@@ -1,36 +1,35 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
2
  import type { GraphViewProjectionV1 } from "../telemetry/graphView";
3
3
  /**
4
- * Endpoint HTTP **additivo** que sirve la proyección reference-only de la vista
5
- * del grafo (GE-082): `GET /api/graph` (JSON) y el marco SSE `event: graph` que
6
- * se empuja en cada cambio de runtime por el canal `/events` existente.
4
+ * Additive HTTP endpoint serving the graph view's reference-only projection
5
+ * (GE-082): `GET /api/graph` (JSON) and the SSE `event: graph` frame pushed on
6
+ * every runtime change through the existing `/events` channel.
7
7
  *
8
- * Seguridad — **paridad de token con `/api/state`**: cuando la Console se expone
9
- * en remoto (con `storageApi`), `remoteToken` exige el mismo token efímero que el
10
- * resto de rutas de lectura; sin él → 401. En loopback puro (`remoteToken`
11
- * indefinido) queda abierto, igual que `/api/state`.
8
+ * Security — **token parity with `/api/state`**: when the Console is exposed
9
+ * remotely (with `storageApi`), `remoteToken` requires the same ephemeral token
10
+ * as the other read routes; without it → 401. On pure loopback
11
+ * (`remoteToken` undefined), it stays open like `/api/state`.
12
12
  *
13
- * Solo lectura y additivo: ninguna página enlaza este endpoint todavía, así que
14
- * la Console por defecto (sin `graphApi` inyectado) es idéntica a hoy.
13
+ * Read-only and additive: if no `graphApi` is wired, the route answers a typed
14
+ * disabled envelope so the shell can explain how to re-enable the tree.
15
15
  */
16
16
  export type GraphRouteDeps = {
17
- /** Proyección actual de la vista, o `null` cuando no hay run activo. */
17
+ /** Current graph-view projection, or `null` when there is no active run. */
18
18
  readView: () => Promise<GraphViewProjectionV1 | null>;
19
19
  /**
20
- * Token de exposición remota, en paridad con `/api/state`. `undefined` en
21
- * loopback puro (ruta abierta).
20
+ * Remote-exposure token, in parity with `/api/state`. `undefined` on pure
21
+ * loopback (open route).
22
22
  */
23
23
  remoteToken?: string;
24
24
  };
25
25
  /**
26
26
  * Payload served by `GET /api/graph` when no graph provider is wired.
27
27
  *
28
- * Lighting up the agent tree requires two independent opt-ins, both off by
29
- * default: `graph.mode` (must not be `"off"`) and `console.graphView.enabled`.
30
- * Before #155 the route simply did not mount in that case, so a default install
31
- * got a bare 404 and the UI could not distinguish "the graph is off" from "this
32
- * console has no such endpoint". Answering a typed envelope lets the agent-tree
33
- * screen render the remediation hint instead of a dead panel.
28
+ * Lighting up the agent tree requires `graph.mode` to be non-`"off"` and
29
+ * `console.graphView.enabled` to be `true`. Those are now defaults, but this
30
+ * envelope remains important when an operator explicitly disables either side:
31
+ * the UI can distinguish "the graph is off" from "this console has no such
32
+ * endpoint" and render the remediation hint instead of a dead panel.
34
33
  */
35
34
  export type GraphDisabledEnvelope = {
36
35
  readonly disabled: true;
@@ -40,9 +39,9 @@ export type GraphDisabledEnvelope = {
40
39
  /** Remediation text naming both flags the operator has to set. */
41
40
  export declare const GRAPH_DISABLED_REMEDIATION: 'Agent tree is off. In .opencode/openteam.json set graph.mode to a value other than "off" and console.graphView.enabled to true, then restart the console.';
42
41
  export declare const GRAPH_DISABLED_ENVELOPE: GraphDisabledEnvelope;
43
- /** Tipo de evento SSE del canal de grafo, multiplexado sobre `/events`. */
42
+ /** SSE event type for the graph channel, multiplexed over `/events`. */
44
43
  export declare const GRAPH_SSE_EVENT: "graph";
45
- /** Marco SSE del canal de grafo para un payload JSON ya serializado. */
44
+ /** Graph-channel SSE frame for an already serialized JSON payload. */
46
45
  export declare function graphSseMessage(json: string): string;
47
46
  /**
48
47
  * Enruta `GET /api/graph`. Devuelve `true` si atendió (y respondió) la petición,
@@ -1 +1 @@
1
- {"version":3,"file":"graphRoute.d.ts","sourceRoot":"","sources":["../../src/web/graphRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,wEAAwE;IACxE,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACtD;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,0BAA0B,EACrC,2JAAoK,CAAC;AAEvK,eAAO,MAAM,uBAAuB,EAAE,qBAIrC,CAAC;AAIF,2EAA2E;AAC3E,eAAO,MAAM,eAAe,EAAG,OAAgB,CAAC;AAEhD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAoBD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,OAAO,CAAC,CAsBlB"}
1
+ {"version":3,"file":"graphRoute.d.ts","sourceRoot":"","sources":["../../src/web/graphRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACtD;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,0BAA0B,EACrC,2JAAoK,CAAC;AAEvK,eAAO,MAAM,uBAAuB,EAAE,qBAIrC,CAAC;AAIF,wEAAwE;AACxE,eAAO,MAAM,eAAe,EAAG,OAAgB,CAAC;AAEhD,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAoBD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,EACxB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,OAAO,CAAC,CAsBlB"}
@@ -67,9 +67,9 @@ export type ConsoleServerDeps = {
67
67
  * (`console.graphView.enabled`) but the graph engine is off (`graph.mode` ==
68
68
  * "off"), so no `graphApi` provider is wired. The shell still mounts the
69
69
  * agent-tree tab and renders the `graph.mode` remediation hint instead of a
70
- * bare-missing tab (PRD W7 acceptance #9). `/api/graph` and the SSE `graph`
71
- * frame stay absent because they follow `graphApi`. Absent/`false` → behaviour
72
- * is identical to today.
70
+ * bare-missing tab (PRD W7 acceptance #9). `GET /api/graph` still answers a
71
+ * disabled envelope; the SSE `graph` frame stays absent because it follows
72
+ * `graphApi`. Absent/`false` means the tree is not marked disabled.
73
73
  */
74
74
  graphDisabled?: boolean;
75
75
  };
@@ -52,10 +52,9 @@ export type ConsoleRuntimeDeps = {
52
52
  /** Endpoint remoto de storage (`/storage/*`). Opcional y opt-in. */
53
53
  storageApi?: StorageRouteDeps;
54
54
  /**
55
- * Proveedor reference-only de la vista del grafo (GE-083). Solo se cablea como
56
- * `graphApi` (activando `/api/graph`, el canal SSE `graph` y el render del DAG)
57
- * cuando `config.graphView.enabled` es `true`; en caso contrario la Console es
58
- * idéntica a hoy.
55
+ * Reference-only graph-view provider (GE-083). Wired as `graphApi` (enabling
56
+ * `/api/graph`, the `graph` SSE channel, and DAG rendering) when
57
+ * `config.graphView.enabled` is `true`; explicit `false` keeps it disabled.
59
58
  */
60
59
  graphView?: {
61
60
  readView: () => Promise<GraphViewProjectionV1 | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/web/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAIpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,aAAa,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,aAAa,CAAC;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,eAAe,EAAE,eAAe,CAAC;IACpD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,OAAO,EAAE,eAAe,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACtD,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,sEAAsE;IACtE,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,aAAa,CAAC;QAClD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC;KACnD,CAAC;IACF,oEAAoE;IACpE,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;KACvD,CAAC;IACF,8BAA8B;IAC9B,KAAK,CAAC,EAAE,cAAc,UAAU,EAAE,mBAAmB,CAAC;IACtD,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;IAC3E,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,cAAc,CAAC,CAEzB"}
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/web/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAIpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,aAAa,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,aAAa,CAAC;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,eAAe,EAAE,eAAe,CAAC;IACpD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,OAAO,EAAE,eAAe,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACtD,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,sEAAsE;IACtE,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,aAAa,CAAC;QAClD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC;KACnD,CAAC;IACF,oEAAoE;IACpE,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,MAAM,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;KACvD,CAAC;IACF,8BAA8B;IAC9B,KAAK,CAAC,EAAE,cAAc,UAAU,EAAE,mBAAmB,CAAC;IACtD,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;IAC3E,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,cAAc,CAAC,CAEzB"}