opencode-orchestrator 1.3.10 → 1.3.12

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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![MIT License](https://img.shields.io/badge/license-MIT-red.svg)](LICENSE)
7
7
  [![npm](https://img.shields.io/npm/v/opencode-orchestrator.svg)](https://www.npmjs.com/package/opencode-orchestrator)
8
8
  <!-- VERSION:START -->
9
- **Version:** `1.3.10`
9
+ **Version:** `1.3.12`
10
10
  <!-- VERSION:END -->
11
11
  </div>
12
12
 
@@ -128,6 +128,7 @@ Runtime evidence is written only when enabled:
128
128
  | `.opencode/mission-ledger.jsonl` | Bounded event trail for mission decisions. |
129
129
  | `.opencode/docs/brain/scratchpad.md` | Generated Markdown memory surface for active missions. |
130
130
  | `.opencode/docs/brain/knowledge-map.canvas` | Obsidian-compatible visual map of objective, evidence, and verification nodes. |
131
+ | `.opencode/docs/brain/memories/*.md` | Generated mission-relevant memory notes indexed by the knowledge retriever. |
131
132
 
132
133
  ## 5. Developer Notes
133
134
 
@@ -4,5 +4,6 @@ export declare class KnowledgeContextProvider {
4
4
  private walkDirectory;
5
5
  private indexKnowledge;
6
6
  private buildSnippet;
7
+ private isDirectInjectedScratchpad;
7
8
  private formatPrompt;
8
9
  }
@@ -2,3 +2,5 @@ import type { MissionLoopState } from "../../shared/loop/interfaces/mission-loop
2
2
  export declare function syncMissionMemory(directory: string, state: MissionLoopState): boolean;
3
3
  export declare function getMissionScratchpadPath(directory: string): string;
4
4
  export declare function getMissionCanvasPath(directory: string): string;
5
+ export declare function getMissionMemoryNotesDirPath(directory: string): string;
6
+ export declare function readMissionScratchpadSnapshot(directory: string, maxChars?: number): string | null;
package/dist/index.js CHANGED
@@ -36437,7 +36437,7 @@ init_logger();
36437
36437
  // src/core/loop/mission-loop.ts
36438
36438
  init_logger();
36439
36439
  init_shared();
36440
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync, mkdirSync as mkdirSync4 } from "node:fs";
36440
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4 } from "node:fs";
36441
36441
  import { join as join6 } from "node:path";
36442
36442
 
36443
36443
  // src/shared/constants/system-messages.ts
@@ -36548,7 +36548,7 @@ You must maintain a pristine workspace. **As part of your move**, perform these
36548
36548
 
36549
36549
  // src/core/knowledge/mission-memory.ts
36550
36550
  init_shared();
36551
- import { mkdirSync as mkdirSync3, renameSync, writeFileSync } from "node:fs";
36551
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, readdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
36552
36552
  import { dirname as dirname2, join as join5 } from "node:path";
36553
36553
 
36554
36554
  // src/core/loop/mission-ledger.ts
@@ -36625,8 +36625,17 @@ function parseLedgerLine(line) {
36625
36625
  var BRAIN_DIR = join5(PATHS.DOCS, "brain");
36626
36626
  var SCRATCHPAD_FILE = "scratchpad.md";
36627
36627
  var CANVAS_FILE = "knowledge-map.canvas";
36628
+ var MEMORY_NOTES_DIR = "memories";
36628
36629
  var MAX_CANVAS_EVENTS = 3;
36629
36630
  var MAX_SCRATCHPAD_EVENTS = 6;
36631
+ var MAX_MEMORY_NOTES = 8;
36632
+ var MAX_MEMORY_BODY_CHARS = 900;
36633
+ var SCRATCHPAD_SNAPSHOT_CHARS = 1600;
36634
+ var MISSION_MEMORY_LEVELS = [
36635
+ "project" /* PROJECT */,
36636
+ "mission" /* MISSION */,
36637
+ "task" /* TASK */
36638
+ ];
36630
36639
  function syncMissionMemory(directory, state2) {
36631
36640
  const options = getMissionRuntimeOptions();
36632
36641
  if (!options.markdownMemory) return false;
@@ -36637,6 +36646,7 @@ function syncMissionMemory(directory, state2) {
36637
36646
  try {
36638
36647
  writeScratchpad(directory, state2, events);
36639
36648
  writeCanvas(directory, state2, events);
36649
+ syncMissionMemoryNotes(directory, state2);
36640
36650
  return true;
36641
36651
  } catch {
36642
36652
  return false;
@@ -36648,6 +36658,17 @@ function getMissionScratchpadPath(directory) {
36648
36658
  function getMissionCanvasPath(directory) {
36649
36659
  return join5(directory, BRAIN_DIR, CANVAS_FILE);
36650
36660
  }
36661
+ function getMissionMemoryNotesDirPath(directory) {
36662
+ return join5(directory, BRAIN_DIR, MEMORY_NOTES_DIR);
36663
+ }
36664
+ function readMissionScratchpadSnapshot(directory, maxChars = SCRATCHPAD_SNAPSHOT_CHARS) {
36665
+ const path11 = getMissionScratchpadPath(directory);
36666
+ if (!existsSync3(path11)) return null;
36667
+ const content = stripFrontmatter(readFileSync2(path11, "utf8")).trim();
36668
+ if (!content) return null;
36669
+ if (content.length <= maxChars) return content;
36670
+ return `${content.slice(0, maxChars)}...`;
36671
+ }
36651
36672
  function writeScratchpad(directory, state2, events) {
36652
36673
  const content = [
36653
36674
  "---",
@@ -36682,6 +36703,22 @@ function writeCanvas(directory, state2, events) {
36682
36703
  const edges = buildCanvasEdges(nodes);
36683
36704
  atomicWrite(getMissionCanvasPath(directory), JSON.stringify({ nodes, edges }, null, 2));
36684
36705
  }
36706
+ function syncMissionMemoryNotes(directory, state2) {
36707
+ const notesDir = getMissionMemoryNotesDirPath(directory);
36708
+ const expectedFiles = /* @__PURE__ */ new Set();
36709
+ for (const entry of selectMissionMemoryEntries(state2)) {
36710
+ const fileName = buildMemoryNoteFileName(entry);
36711
+ expectedFiles.add(fileName);
36712
+ atomicWrite(join5(notesDir, fileName), buildMemoryNoteContent(state2, entry));
36713
+ }
36714
+ if (!existsSync3(notesDir)) return;
36715
+ for (const entry of readdirSync(notesDir, { withFileTypes: true })) {
36716
+ if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
36717
+ if (!expectedFiles.has(entry.name)) {
36718
+ unlinkSync(join5(notesDir, entry.name));
36719
+ }
36720
+ }
36721
+ }
36685
36722
  function buildCanvasNodes(state2, events) {
36686
36723
  const nodes = [
36687
36724
  textNode("objective", `Objective
@@ -36711,6 +36748,67 @@ function buildCanvasEdges(nodes) {
36711
36748
  function textNode(id, text, x, y) {
36712
36749
  return { id, type: "text", text, x, y, width: 360, height: 180 };
36713
36750
  }
36751
+ function selectMissionMemoryEntries(state2) {
36752
+ const snapshot = MemoryManager.getInstance().export();
36753
+ const query = `${state2.objective ?? ""} ${state2.prompt}`.trim();
36754
+ const selected = [];
36755
+ for (const level of MISSION_MEMORY_LEVELS) {
36756
+ const entries = snapshot[level] ?? [];
36757
+ for (const entry of entries) {
36758
+ if (shouldPersistMissionEntry(entry, level, query)) {
36759
+ selected.push(entry);
36760
+ }
36761
+ }
36762
+ }
36763
+ return selected.sort((left, right) => right.importance - left.importance || right.timestamp - left.timestamp).slice(0, MAX_MEMORY_NOTES);
36764
+ }
36765
+ function shouldPersistMissionEntry(entry, level, query) {
36766
+ const matchesQuery = query ? isRelevantToQuery(entry.content, query) : false;
36767
+ switch (level) {
36768
+ case "project" /* PROJECT */:
36769
+ return entry.importance >= 0.7 || matchesQuery;
36770
+ case "mission" /* MISSION */:
36771
+ return entry.importance >= 0.5 || matchesQuery;
36772
+ case "task" /* TASK */:
36773
+ return entry.importance >= 0.7 || matchesQuery;
36774
+ default:
36775
+ return false;
36776
+ }
36777
+ }
36778
+ function isRelevantToQuery(content, query) {
36779
+ const normalizedContent = content.toLowerCase();
36780
+ const keywords = query.toLowerCase().split(/\s+/).map((token) => token.trim()).filter((token) => token.length > 3);
36781
+ if (keywords.length === 0) return false;
36782
+ return keywords.some((keyword) => normalizedContent.includes(keyword));
36783
+ }
36784
+ function buildMemoryNoteFileName(entry) {
36785
+ return `${entry.level}-${sanitizeFilePart(entry.id)}.md`;
36786
+ }
36787
+ function buildMemoryNoteContent(state2, entry) {
36788
+ const recordedAt = new Date(entry.timestamp).toISOString();
36789
+ const body = entry.content.length > MAX_MEMORY_BODY_CHARS ? `${entry.content.slice(0, MAX_MEMORY_BODY_CHARS)}...` : entry.content;
36790
+ return [
36791
+ "---",
36792
+ `tags: [mission-memory, orchestrator, ${entry.level}]`,
36793
+ `title: "${escapeYaml(`${entry.level} memory ${entry.id}`)}"`,
36794
+ "keep: true",
36795
+ `level: "${entry.level}"`,
36796
+ `importance: ${entry.importance.toFixed(3)}`,
36797
+ `session: "${escapeYaml(state2.sessionID)}"`,
36798
+ `recorded_at: "${recordedAt}"`,
36799
+ `objective: "${escapeYaml(state2.objective ?? state2.prompt)}"`,
36800
+ "---",
36801
+ `# ${capitalize(entry.level)} Memory`,
36802
+ "",
36803
+ `- Session: ${state2.sessionID}`,
36804
+ `- Recorded at: ${recordedAt}`,
36805
+ `- Importance: ${entry.importance.toFixed(3)}`,
36806
+ "",
36807
+ "## Content",
36808
+ body,
36809
+ ""
36810
+ ].join("\n");
36811
+ }
36714
36812
  function formatEventLines(events) {
36715
36813
  if (events.length === 0) return ["- No runtime evidence recorded yet."];
36716
36814
  return events.map((event) => `- ${event.timestamp} ${event.type}: ${event.summary ?? event.reason ?? "recorded"}`);
@@ -36724,6 +36822,15 @@ function atomicWrite(path11, content) {
36724
36822
  function escapeYaml(value) {
36725
36823
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
36726
36824
  }
36825
+ function stripFrontmatter(content) {
36826
+ return content.replace(/^---\n[\s\S]*?\n---\n?/u, "");
36827
+ }
36828
+ function sanitizeFilePart(value) {
36829
+ return value.replace(/[^a-zA-Z0-9_-]+/g, "-");
36830
+ }
36831
+ function capitalize(value) {
36832
+ return value.charAt(0).toUpperCase() + value.slice(1);
36833
+ }
36727
36834
 
36728
36835
  // src/core/loop/mission-loop.ts
36729
36836
  var STATE_FILE = MISSION_CONTROL.STATE_FILE;
@@ -36734,11 +36841,11 @@ function getStateFilePath(directory) {
36734
36841
  }
36735
36842
  function readLoopState(directory) {
36736
36843
  const filePath = getStateFilePath(directory);
36737
- if (!existsSync3(filePath)) {
36844
+ if (!existsSync4(filePath)) {
36738
36845
  return null;
36739
36846
  }
36740
36847
  try {
36741
- const content = readFileSync2(filePath, "utf-8");
36848
+ const content = readFileSync3(filePath, "utf-8");
36742
36849
  return JSON.parse(content);
36743
36850
  } catch (error95) {
36744
36851
  log(`[${MISSION_CONTROL.LOG_SOURCE}] Failed to read state: ${error95}`);
@@ -36749,7 +36856,7 @@ function writeLoopState(directory, state2) {
36749
36856
  const filePath = getStateFilePath(directory);
36750
36857
  const dirPath = join6(directory, PATHS.OPENCODE);
36751
36858
  try {
36752
- if (!existsSync3(dirPath)) {
36859
+ if (!existsSync4(dirPath)) {
36753
36860
  mkdirSync4(dirPath, { recursive: true });
36754
36861
  }
36755
36862
  writeFileSync2(filePath, JSON.stringify(state2, null, 2), "utf-8");
@@ -36761,11 +36868,11 @@ function writeLoopState(directory, state2) {
36761
36868
  }
36762
36869
  function clearLoopState(directory) {
36763
36870
  const filePath = getStateFilePath(directory);
36764
- if (!existsSync3(filePath)) {
36871
+ if (!existsSync4(filePath)) {
36765
36872
  return false;
36766
36873
  }
36767
36874
  try {
36768
- unlinkSync(filePath);
36875
+ unlinkSync2(filePath);
36769
36876
  return true;
36770
36877
  } catch (error95) {
36771
36878
  log(`[${MISSION_CONTROL.LOG_SOURCE}] Failed to clear state: ${error95}`);
@@ -37251,7 +37358,7 @@ ${commandList}`;
37251
37358
  // src/core/loop/verification.ts
37252
37359
  init_shared();
37253
37360
  init_logger();
37254
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
37361
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
37255
37362
  import { join as join7 } from "node:path";
37256
37363
  var CHECKLIST_FILE = CHECKLIST.FILE;
37257
37364
  function parseChecklistLine(line, currentCategory) {
@@ -37318,11 +37425,11 @@ function parseChecklist(content) {
37318
37425
  }
37319
37426
  function readChecklist(directory) {
37320
37427
  const filePath = join7(directory, CHECKLIST_FILE);
37321
- if (!existsSync4(filePath)) {
37428
+ if (!existsSync5(filePath)) {
37322
37429
  return [];
37323
37430
  }
37324
37431
  try {
37325
- const content = readFileSync3(filePath, "utf-8");
37432
+ const content = readFileSync4(filePath, "utf-8");
37326
37433
  return parseChecklist(content);
37327
37434
  } catch (error95) {
37328
37435
  log(`[checklist] Failed to read checklist: ${error95}`);
@@ -37340,7 +37447,7 @@ function verifyChecklist(directory) {
37340
37447
  errors: []
37341
37448
  };
37342
37449
  const filePath = join7(directory, CHECKLIST_FILE);
37343
- if (!existsSync4(filePath)) {
37450
+ if (!existsSync5(filePath)) {
37344
37451
  result.errors.push(`Verification checklist not found at ${CHECKLIST_FILE}`);
37345
37452
  result.errors.push("Create checklist with at least: build, tests, and any environment-specific checks");
37346
37453
  return result;
@@ -37417,9 +37524,9 @@ function verifyMissionCompletion(directory) {
37417
37524
  }
37418
37525
  }
37419
37526
  const todoPath = join7(directory, PATHS.TODO);
37420
- if (existsSync4(todoPath)) {
37527
+ if (existsSync5(todoPath)) {
37421
37528
  try {
37422
- const content = readFileSync3(todoPath, "utf-8");
37529
+ const content = readFileSync4(todoPath, "utf-8");
37423
37530
  const incompleteCount = countMatches(content, TODO_INCOMPLETE_PATTERN);
37424
37531
  const completeCount = countMatches(content, TODO_COMPLETE_PATTERN);
37425
37532
  const total = incompleteCount + completeCount;
@@ -37442,9 +37549,9 @@ function verifyMissionCompletion(directory) {
37442
37549
  result.errors.push(`TODO file not found at ${PATHS.TODO}`);
37443
37550
  }
37444
37551
  const syncPath = join7(directory, PATHS.SYNC_ISSUES);
37445
- if (existsSync4(syncPath)) {
37552
+ if (existsSync5(syncPath)) {
37446
37553
  try {
37447
- const content = readFileSync3(syncPath, "utf-8");
37554
+ const content = readFileSync4(syncPath, "utf-8");
37448
37555
  result.syncIssuesEmpty = !hasRealSyncIssues(content);
37449
37556
  if (!result.syncIssuesEmpty) {
37450
37557
  const issueLines = content.split("\n").filter(
@@ -37532,7 +37639,7 @@ function buildVerificationSummary(result) {
37532
37639
  init_logger();
37533
37640
  import { exec as exec2 } from "node:child_process";
37534
37641
  import { promisify as promisify2 } from "node:util";
37535
- import { readFileSync as readFileSync4 } from "node:fs";
37642
+ import { readFileSync as readFileSync5 } from "node:fs";
37536
37643
 
37537
37644
  // src/shared/notification/os-notify/constants/notification-commands.ts
37538
37645
  var NOTIFICATION_COMMANDS = {
@@ -37610,7 +37717,7 @@ async function notifyDarwin(title, message) {
37610
37717
  function isWSL() {
37611
37718
  try {
37612
37719
  if (process.env.WSL_DISTRO_NAME || process.env.WSLENV) return true;
37613
- const procVersion = readFileSync4("/proc/version", "utf-8");
37720
+ const procVersion = readFileSync5("/proc/version", "utf-8");
37614
37721
  return /microsoft|WSL/i.test(procVersion);
37615
37722
  } catch {
37616
37723
  return false;
@@ -39131,9 +39238,9 @@ import * as path6 from "node:path";
39131
39238
 
39132
39239
  // src/core/cache/utils.ts
39133
39240
  import * as fs6 from "node:fs/promises";
39134
- import { existsSync as existsSync6 } from "node:fs";
39241
+ import { existsSync as existsSync7 } from "node:fs";
39135
39242
  async function ensureCacheDir() {
39136
- if (!existsSync6(CACHE_DIR)) {
39243
+ if (!existsSync7(CACHE_DIR)) {
39137
39244
  await fs6.mkdir(CACHE_DIR, { recursive: true });
39138
39245
  }
39139
39246
  }
@@ -39635,14 +39742,14 @@ var backgroundTaskManager = BackgroundTaskManager.instance;
39635
39742
 
39636
39743
  // src/tools/rust-pool.ts
39637
39744
  import { spawn as spawn2 } from "child_process";
39638
- import { existsSync as existsSync9 } from "fs";
39745
+ import { existsSync as existsSync10 } from "fs";
39639
39746
 
39640
39747
  // src/utils/binary.ts
39641
39748
  init_shared();
39642
39749
  import { join as join12, dirname as dirname5 } from "path";
39643
39750
  import { fileURLToPath } from "url";
39644
39751
  import { platform, arch } from "os";
39645
- import { existsSync as existsSync8 } from "fs";
39752
+ import { existsSync as existsSync9 } from "fs";
39646
39753
  var __dirname = dirname5(fileURLToPath(import.meta.url));
39647
39754
  function getPlatformBinaryName(os = platform(), cpu = arch()) {
39648
39755
  if (os === PLATFORM.WIN32) {
@@ -39663,7 +39770,7 @@ function resolveBinaryPath(options = {}) {
39663
39770
  const moduleDir = options.moduleDir ?? __dirname;
39664
39771
  const os = options.os ?? platform();
39665
39772
  const cpu = options.cpu ?? arch();
39666
- const exists = options.exists ?? existsSync8;
39773
+ const exists = options.exists ?? existsSync9;
39667
39774
  const binaryName = getPlatformBinaryName(os, cpu);
39668
39775
  for (const binDir of getCandidateBinDirs(moduleDir)) {
39669
39776
  const binaryPath = join12(binDir, binaryName);
@@ -39702,7 +39809,7 @@ var RustToolPool = class {
39702
39809
  constructor(maxSize = 4, options = {}) {
39703
39810
  this.maxSize = maxSize;
39704
39811
  this.binaryPath = options.binaryPath ?? getBinaryPath;
39705
- this.exists = options.exists ?? existsSync9;
39812
+ this.exists = options.exists ?? existsSync10;
39706
39813
  this.idleTimeout = options.idleTimeoutMs ?? this.idleTimeout;
39707
39814
  this.processReadyDelay = options.processReadyDelayMs ?? this.processReadyDelay;
39708
39815
  this.requestTimeout = options.requestTimeoutMs ?? this.requestTimeout;
@@ -42478,7 +42585,7 @@ Wait for these tasks to complete before concluding the mission.
42478
42585
  init_shared();
42479
42586
 
42480
42587
  // src/core/knowledge/context-provider.ts
42481
- import { existsSync as existsSync10, readFileSync as readFileSync6, readdirSync } from "node:fs";
42588
+ import { existsSync as existsSync11, readFileSync as readFileSync7, readdirSync as readdirSync2 } from "node:fs";
42482
42589
  import path10 from "node:path";
42483
42590
 
42484
42591
  // src/core/knowledge/graph-parser.ts
@@ -42772,7 +42879,7 @@ var HybridSearch = class {
42772
42879
  };
42773
42880
 
42774
42881
  // src/core/knowledge/tag-indexer.ts
42775
- import { readFileSync as readFileSync5 } from "node:fs";
42882
+ import { readFileSync as readFileSync6 } from "node:fs";
42776
42883
  var TagIndexer = class {
42777
42884
  tagMap = /* @__PURE__ */ new Map();
42778
42885
  fileCache = /* @__PURE__ */ new Map();
@@ -42846,7 +42953,7 @@ var TagIndexer = class {
42846
42953
  */
42847
42954
  indexFileFromDisk(filePath) {
42848
42955
  try {
42849
- const content = readFileSync5(filePath, "utf8");
42956
+ const content = readFileSync6(filePath, "utf8");
42850
42957
  this.indexFile(filePath, content);
42851
42958
  } catch {
42852
42959
  this.clearIndexForFile(filePath);
@@ -42946,6 +43053,7 @@ var MAX_RESULTS = 3;
42946
43053
  var MAX_SNIPPET_CHARS = 220;
42947
43054
  var KNOWLEDGE_ROOTS = ["docs", path10.join(".opencode", "docs")];
42948
43055
  var SKIP_SEGMENTS = /* @__PURE__ */ new Set(["node_modules", "dist", "bin", ".git", "archive"]);
43056
+ var GENERATED_SCRATCHPAD_PATH = path10.join(".opencode", "docs", "brain", "scratchpad.md");
42949
43057
  var KnowledgeContextProvider = class {
42950
43058
  buildPrompt(directory, query) {
42951
43059
  const normalizedQuery = query.trim();
@@ -42961,14 +43069,14 @@ var KnowledgeContextProvider = class {
42961
43069
  const files = [];
42962
43070
  for (const root of KNOWLEDGE_ROOTS) {
42963
43071
  const fullRoot = path10.join(directory, root);
42964
- if (!existsSync10(fullRoot)) continue;
43072
+ if (!existsSync11(fullRoot)) continue;
42965
43073
  files.push(...this.walkDirectory(fullRoot));
42966
43074
  }
42967
- return files.sort();
43075
+ return files.filter((filePath) => !this.isDirectInjectedScratchpad(directory, filePath)).sort();
42968
43076
  }
42969
43077
  walkDirectory(directory) {
42970
43078
  const files = [];
42971
- for (const entry of readdirSync(directory, { withFileTypes: true })) {
43079
+ for (const entry of readdirSync2(directory, { withFileTypes: true })) {
42972
43080
  const fullPath = path10.join(directory, entry.name);
42973
43081
  if (entry.isDirectory()) {
42974
43082
  if (SKIP_SEGMENTS.has(entry.name)) continue;
@@ -42989,7 +43097,7 @@ var KnowledgeContextProvider = class {
42989
43097
  const noteToSnippet = /* @__PURE__ */ new Map();
42990
43098
  for (const filePath of files) {
42991
43099
  try {
42992
- const content = readFileSync6(filePath, "utf8");
43100
+ const content = readFileSync7(filePath, "utf8");
42993
43101
  const noteName = graphParser.getNoteName(filePath);
42994
43102
  const { body } = tagIndexer.parseFrontmatter(content);
42995
43103
  const normalizedBody = body.trim();
@@ -43009,6 +43117,9 @@ var KnowledgeContextProvider = class {
43009
43117
  if (normalized.length <= MAX_SNIPPET_CHARS) return normalized;
43010
43118
  return `${normalized.slice(0, MAX_SNIPPET_CHARS)}...`;
43011
43119
  }
43120
+ isDirectInjectedScratchpad(directory, filePath) {
43121
+ return path10.relative(directory, filePath) === GENERATED_SCRATCHPAD_PATH;
43122
+ }
43012
43123
  formatPrompt(query, results, indexed) {
43013
43124
  const lines = [
43014
43125
  "<knowledge_rag_context>",
@@ -43050,13 +43161,17 @@ function createSystemTransformHandler(ctx) {
43050
43161
  const { commander: commander2 } = await Promise.resolve().then(() => (init_commander(), commander_exports));
43051
43162
  systemAdditions.push(commander2.systemPrompt);
43052
43163
  systemAdditions.push(buildMissionLoopSystemPrompt(loopState));
43164
+ const scratchpadPrompt = buildMissionScratchpadPrompt(directory);
43165
+ if (scratchpadPrompt) {
43166
+ systemAdditions.push(scratchpadPrompt);
43167
+ }
43053
43168
  }
43054
43169
  if (session?.active) {
43055
43170
  systemAdditions.push(buildActiveSessionPrompt(session.step));
43056
43171
  }
43057
43172
  const knowledgePrompt = buildKnowledgeContextPrompt(
43058
43173
  directory,
43059
- loopState?.prompt,
43174
+ loopState,
43060
43175
  state2.sessions.get(sessionID)?.currentTask
43061
43176
  );
43062
43177
  if (knowledgePrompt) {
@@ -43077,10 +43192,24 @@ function createSystemTransformHandler(ctx) {
43077
43192
  }
43078
43193
  };
43079
43194
  }
43080
- function buildKnowledgeContextPrompt(directory, missionPrompt, currentTask) {
43081
- const queryParts = [missionPrompt ?? "", currentTask ?? ""].filter(Boolean);
43195
+ function buildKnowledgeContextPrompt(directory, loopState, currentTask) {
43196
+ const queryParts = [
43197
+ loopState?.objective ?? "",
43198
+ loopState?.prompt ?? "",
43199
+ currentTask ?? "",
43200
+ loopState?.lastProgress ?? "",
43201
+ loopState?.lastVerificationSummary ?? "",
43202
+ loopState?.lastContinuationReason ?? ""
43203
+ ].filter(Boolean);
43082
43204
  return knowledgeContextProvider.buildPrompt(directory, queryParts.join(" ").trim());
43083
43205
  }
43206
+ function buildMissionScratchpadPrompt(directory) {
43207
+ const snapshot = readMissionScratchpadSnapshot(directory);
43208
+ if (!snapshot) return null;
43209
+ return `<mission_scratchpad path="${PATHS.DOCS}/brain/scratchpad.md">
43210
+ ${snapshot}
43211
+ </mission_scratchpad>`;
43212
+ }
43084
43213
  function buildMissionLoopSystemPrompt(loopState) {
43085
43214
  return `<orchestrator_mission_loop>
43086
43215
  \u{1F3AF} MISSION LOOP ACTIVE: Iteration ${loopState.iteration}/${loopState.maxIterations}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "opencode-orchestrator",
3
3
  "displayName": "OpenCode Orchestrator",
4
4
  "description": "Multi-agent mission control for OpenCode with Commander, Planner, Worker, and Reviewer workflows.",
5
- "version": "1.3.10",
5
+ "version": "1.3.12",
6
6
  "author": "agnusdei1207",
7
7
  "license": "MIT",
8
8
  "repository": {