@osovv/vv-opencode 0.11.0 → 0.13.0

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
@@ -7,6 +7,7 @@ Portable OpenCode workflow package with plugins and a Bun CLI for setup, sync, d
7
7
  - `vvoc` CLI for bootstrap, sync, inspection, and model overrides
8
8
  - `GuardianPlugin` for permission review
9
9
  - `MemoryPlugin` for explicit persistent memory
10
+ - `SystemContextInjectionPlugin` for reusable primary-session system guidance
10
11
  - `SecretsRedactionPlugin` for redacting secrets before LLM requests
11
12
  - report-only `memory-reviewer` subagent
12
13
  - vvoc-managed prompt files and OpenCode agent registrations
@@ -49,7 +50,7 @@ vvoc install --scope project
49
50
  - keeps vvoc-managed config separate from native OpenCode config
50
51
  - leaves unmanaged files alone unless `--force` is passed
51
52
 
52
- For conversational meta-prompting, use the managed `enhancer` primary agent. It can ask follow-up questions and then return a clean XML prompt with semantically unique repeated tags such as `<constraint-1>...</constraint-1>` and `<verification-check-2>...</verification-check-2>`.
53
+ For conversational meta-prompting, use the managed `enhancer` primary agent. It can ask follow-up questions and then return a clean XML prompt in English with semantically unique repeated tags such as `<constraint-1>...</constraint-1>` and `<verification-check-2>...</verification-check-2>`.
53
54
 
54
55
  Typical workflow:
55
56
 
@@ -69,7 +70,7 @@ The OpenCode config entry written by `install` looks like this:
69
70
  }
70
71
  ```
71
72
 
72
- That package entry points at the package root, which exports `GuardianPlugin`, `MemoryPlugin`, and `SecretsRedactionPlugin`.
73
+ That package entry points at the package root, which exports `GuardianPlugin`, `MemoryPlugin`, `SystemContextInjectionPlugin`, and `SecretsRedactionPlugin`.
73
74
 
74
75
  ## Common Workflows
75
76
 
@@ -313,6 +314,14 @@ Example:
313
314
 
314
315
  The reviewer can read memory but cannot modify it.
315
316
 
317
+ ### SystemContextInjectionPlugin
318
+
319
+ `SystemContextInjectionPlugin` injects reusable system guidance into primary chat sessions without polluting known subagent prompts.
320
+
321
+ The default injected guidance tells the main session to proactively use the `explore` subagent when the task depends on unfamiliar code, unclear scope, or multiple candidate implementation areas.
322
+
323
+ The plugin currently injects guidance through the `chat.message` hook so it can inspect the resolved agent name and skip known subagents such as `general`, `explore`, `implementer`, and `memory-reviewer`.
324
+
316
325
  ### SecretsRedactionPlugin
317
326
 
318
327
  `SecretsRedactionPlugin` redacts secrets from chat content before LLM requests and restores placeholders after the request lifecycle where needed.
@@ -372,6 +381,7 @@ Root exports:
372
381
  import {
373
382
  GuardianPlugin,
374
383
  MemoryPlugin,
384
+ SystemContextInjectionPlugin,
375
385
  SecretsRedactionPlugin,
376
386
  } from "@osovv/vv-opencode";
377
387
  ```
@@ -381,6 +391,7 @@ Subpath exports:
381
391
  ```ts
382
392
  import { GuardianPlugin } from "@osovv/vv-opencode/plugins/guardian";
383
393
  import { MemoryPlugin } from "@osovv/vv-opencode/plugins/memory";
394
+ import { SystemContextInjectionPlugin } from "@osovv/vv-opencode/plugins/system-context-injection";
384
395
  import { SecretsRedactionPlugin } from "@osovv/vv-opencode/plugins/secrets-redaction";
385
396
  ```
386
397
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { GuardianPlugin } from "./plugins/guardian/index.js";
2
2
  export { MemoryPlugin } from "./plugins/memory/index.js";
3
+ export { SystemContextInjectionPlugin } from "./plugins/system-context-injection/index.js";
3
4
  export { SecretsRedactionPlugin } from "./plugins/secrets-redaction.js";
package/dist/index.js CHANGED
@@ -1,22 +1,23 @@
1
1
  // FILE: src/index.ts
2
- // VERSION: 0.4.0
2
+ // VERSION: 0.5.0
3
3
  // START_MODULE_CONTRACT
4
4
  // PURPOSE: Re-export the public vv-opencode plugin entrypoints from the package root.
5
- // SCOPE: Package-root exports for GuardianPlugin, MemoryPlugin, and SecretsRedactionPlugin.
6
- // DEPENDS: [src/plugins/guardian/index.ts, src/plugins/memory/index.ts, src/plugins/secrets-redaction.ts]
7
- // LINKS: [M-PLUGIN-GUARDIAN, M-PLUGIN-MEMORY, M-PLUGIN-SECRETS-REDACTION]
5
+ // SCOPE: Package-root exports for GuardianPlugin, MemoryPlugin, SystemContextInjectionPlugin, and SecretsRedactionPlugin.
6
+ // DEPENDS: [src/plugins/guardian/index.ts, src/plugins/memory/index.ts, src/plugins/system-context-injection/index.ts, src/plugins/secrets-redaction.ts]
7
+ // LINKS: [M-PLUGIN-GUARDIAN, M-PLUGIN-MEMORY, M-PLUGIN-SYSTEM-CONTEXT-INJECTION, M-PLUGIN-SECRETS-REDACTION]
8
8
  // ROLE: BARREL
9
9
  // MAP_MODE: SUMMARY
10
10
  // END_MODULE_CONTRACT
11
11
  //
12
12
  // START_MODULE_MAP
13
- // GuardianPlugin, MemoryPlugin, SecretsRedactionPlugin - Public plugin exports available from @osovv/vv-opencode.
13
+ // GuardianPlugin, MemoryPlugin, SystemContextInjectionPlugin, SecretsRedactionPlugin - Public plugin exports available from @osovv/vv-opencode.
14
14
  // END_MODULE_MAP
15
15
  //
16
16
  // START_CHANGE_SUMMARY
17
- // LAST_CHANGE: [v0.4.0 - Removed the legacy enhance runtime plugin export after dropping the old enhance command path.]
17
+ // LAST_CHANGE: [v0.5.0 - Added SystemContextInjectionPlugin to the package-root plugin exports.]
18
18
  // END_CHANGE_SUMMARY
19
19
  export { GuardianPlugin } from "./plugins/guardian/index.js";
20
20
  export { MemoryPlugin } from "./plugins/memory/index.js";
21
+ export { SystemContextInjectionPlugin } from "./plugins/system-context-injection/index.js";
21
22
  export { SecretsRedactionPlugin } from "./plugins/secrets-redaction.js";
22
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,iBAAiB;AACjB,wBAAwB;AACxB,wFAAwF;AACxF,8FAA8F;AAC9F,4GAA4G;AAC5G,4EAA4E;AAC5E,iBAAiB;AACjB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,oHAAoH;AACpH,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,0HAA0H;AAC1H,qBAAqB;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,iBAAiB;AACjB,wBAAwB;AACxB,wFAAwF;AACxF,4HAA4H;AAC5H,2JAA2J;AAC3J,+GAA+G;AAC/G,iBAAiB;AACjB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,kJAAkJ;AAClJ,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,mGAAmG;AACnG,qBAAqB;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,6CAA6C,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -1,8 +1,8 @@
1
1
  // FILE: src/plugins/secrets-redaction/engine.ts
2
- // VERSION: 1.0.0
2
+ // VERSION: 1.1.0
3
3
  // START_MODULE_CONTRACT
4
4
  // PURPOSE: Core redaction engine — performs find/replace of secrets with placeholders in text.
5
- // SCOPE: text scanning, match sorting, interval arithmetic, replacement
5
+ // SCOPE: text scanning, overlap resolution, match sorting, and replacement
6
6
  // DEPENDS: session, patterns
7
7
  // LINKS: knowledge-graph://plugins/secrets-redaction
8
8
  // ROLE: RUNTIME
@@ -12,37 +12,11 @@
12
12
  // START_MODULE_MAP
13
13
  // redactText - replaces secrets in text with placeholders, returns changed text + match list
14
14
  // END_MODULE_MAP
15
- function subtractCovered(intervals) {
16
- if (intervals.length === 0)
17
- return [];
18
- intervals.sort((a, b) => a[0] - b[0]);
19
- const result = [];
20
- let currentEnd = intervals[0][0];
21
- for (const [start, end] of intervals) {
22
- if (start > currentEnd) {
23
- result.push([currentEnd, start]);
24
- }
25
- if (end > currentEnd) {
26
- currentEnd = end;
27
- }
28
- }
29
- return result;
30
- }
31
- function insertCovered(intervals, newInterval) {
32
- const merged = [...intervals, newInterval];
33
- merged.sort((a, b) => a[0] - b[0]);
34
- const result = [];
35
- for (const interval of merged) {
36
- if (result.length > 0 && interval[0] <= result[result.length - 1][1]) {
37
- result[result.length - 1][1] = Math.max(result[result.length - 1][1], interval[1]);
38
- }
39
- else {
40
- result.push([...interval]);
41
- }
42
- }
43
- return result;
44
- }
45
- function sortByPositionDesc(rules, text) {
15
+ //
16
+ // START_CHANGE_SUMMARY
17
+ // LAST_CHANGE: [v1.1.0 - Fixed overlap handling so first and wider earlier matches redact correctly instead of being skipped entirely.]
18
+ // END_CHANGE_SUMMARY
19
+ function sortByPositionAsc(rules, text) {
46
20
  const allMatches = [];
47
21
  for (const rule of rules) {
48
22
  const re = new RegExp(rule.pattern.source, rule.pattern.flags.includes("g") ? rule.pattern.flags : `${rule.pattern.flags}g`);
@@ -55,17 +29,23 @@ function sortByPositionDesc(rules, text) {
55
29
  const aStart = a.match.index;
56
30
  const bStart = b.match.index;
57
31
  if (aStart !== bStart)
58
- return bStart - aStart;
32
+ return aStart - bStart;
59
33
  return b.match[0].length - a.match[0].length;
60
34
  });
61
35
  return allMatches.map((x) => ({ rule: x.rule, matches: x.match }));
62
36
  }
37
+ function overlapsSelected(start, selected) {
38
+ const lastSelected = selected[selected.length - 1];
39
+ if (!lastSelected) {
40
+ return false;
41
+ }
42
+ return start < lastSelected.end;
43
+ }
63
44
  export function redactText(input, patternSet, session) {
64
45
  if (!input || patternSet.rules.length === 0) {
65
46
  return { text: input, matches: [] };
66
47
  }
67
- const sorted = sortByPositionDesc(patternSet.rules, input);
68
- const covered = [];
48
+ const sorted = sortByPositionAsc(patternSet.rules, input);
69
49
  const matches = [];
70
50
  for (const { rule, matches: match } of sorted) {
71
51
  const start = match.index;
@@ -74,40 +54,20 @@ export function redactText(input, patternSet, session) {
74
54
  if (patternSet.exclude.has(value.toLowerCase())) {
75
55
  continue;
76
56
  }
77
- const gaps = subtractCovered(covered);
78
- const isInside = gaps.every(([gStart, gEnd]) => start >= gStart && end <= gEnd);
79
- if (isInside)
57
+ if (overlapsSelected(start, matches)) {
80
58
  continue;
59
+ }
81
60
  const placeholder = session.getOrCreatePlaceholder(value, rule.category);
82
61
  matches.push({ start, end, original: value, placeholder, category: rule.category });
83
- const remainingGaps = [];
84
- for (const [gStart, gEnd] of gaps) {
85
- if (start >= gEnd || end <= gStart) {
86
- remainingGaps.push([gStart, gEnd]);
87
- }
88
- else {
89
- if (start > gStart) {
90
- remainingGaps.push([gStart, start]);
91
- }
92
- if (end < gEnd) {
93
- remainingGaps.push([end, gEnd]);
94
- }
95
- }
96
- }
97
- covered.length = 0;
98
- for (const g of remainingGaps) {
99
- insertCovered(covered, g);
100
- }
101
62
  }
102
- const sortedMatches = [...matches].sort((a, b) => a.start - b.start);
103
63
  let result = "";
104
64
  let lastIndex = 0;
105
- for (const m of sortedMatches) {
65
+ for (const m of matches) {
106
66
  result += input.slice(lastIndex, m.start);
107
67
  result += m.placeholder;
108
68
  lastIndex = m.end;
109
69
  }
110
70
  result += input.slice(lastIndex);
111
- return { text: result, matches: sortedMatches };
71
+ return { text: result, matches };
112
72
  }
113
73
  //# sourceMappingURL=engine.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/plugins/secrets-redaction/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/plugins/secrets-redaction/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type Plugin } from "@opencode-ai/plugin";
2
+ export declare const SystemContextInjectionPlugin: Plugin;
@@ -0,0 +1,89 @@
1
+ // FILE: src/plugins/system-context-injection/index.ts
2
+ // VERSION: 0.1.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Inject reusable vvoc system context into primary chat sessions without polluting known subagent prompts.
5
+ // SCOPE: Main-session system instruction definitions, known subagent filtering, config-aware custom subagent tracking, and chat.message system prompt injection.
6
+ // DEPENDS: [@opencode-ai/plugin, src/lib/managed-agents.ts]
7
+ // LINKS: [M-PLUGIN-SYSTEM-CONTEXT-INJECTION, M-CLI-MANAGED-AGENTS]
8
+ // ROLE: RUNTIME
9
+ // MAP_MODE: EXPORTS
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // SystemContextInjectionPlugin - Injects reusable system guidance into primary sessions while skipping known subagents.
14
+ // END_MODULE_MAP
15
+ //
16
+ // START_CHANGE_SUMMARY
17
+ // LAST_CHANGE: [v0.1.0 - Added a reusable main-session system context injector with default proactive explore guidance.]
18
+ // END_CHANGE_SUMMARY
19
+ import { MANAGED_SUBAGENT_NAMES } from "../../lib/managed-agents.js";
20
+ const BUILT_IN_SUBAGENTS = ["general", "explore"];
21
+ const PLUGIN_MANAGED_SUBAGENTS = ["guardian", "memory-reviewer"];
22
+ const INTERNAL_PRIMARY_AGENTS = ["compaction", "title", "summary"];
23
+ const MAIN_SESSION_SYSTEM_CONTEXTS = [
24
+ [
25
+ "<proactive_context_gathering>",
26
+ "Before answering questions about the codebase or making changes, proactively use the explore subagent to gather the context you need whenever the task depends on unfamiliar code, unclear scope, or multiple candidate implementation areas.",
27
+ "Do not guess about code you have not inspected.",
28
+ "If the task is already localized and the required context is already in view, work directly instead of delegating.",
29
+ "</proactive_context_gathering>",
30
+ ].join("\n"),
31
+ ];
32
+ // START_BLOCK_AGENT_FILTERS
33
+ function createKnownSubagentSet() {
34
+ return new Set([...BUILT_IN_SUBAGENTS, ...PLUGIN_MANAGED_SUBAGENTS, ...MANAGED_SUBAGENT_NAMES]);
35
+ }
36
+ function syncConfiguredSubagents(config, knownSubagents) {
37
+ for (const [name, definition] of Object.entries(config.agent ?? {})) {
38
+ if (definition?.mode === "subagent") {
39
+ knownSubagents.add(name);
40
+ }
41
+ }
42
+ }
43
+ function shouldInjectForAgent(agentName, knownSubagents) {
44
+ if (!agentName) {
45
+ return false;
46
+ }
47
+ if (knownSubagents.has(agentName)) {
48
+ return false;
49
+ }
50
+ if (INTERNAL_PRIMARY_AGENTS.includes(agentName)) {
51
+ return false;
52
+ }
53
+ return true;
54
+ }
55
+ // END_BLOCK_AGENT_FILTERS
56
+ // START_BLOCK_SYSTEM_CONTEXT_FORMATTING
57
+ function hasInjectedContext(existingSystem, context) {
58
+ return typeof existingSystem === "string" && existingSystem.includes(context);
59
+ }
60
+ function appendSystemContexts(existingSystem, contexts) {
61
+ const parts = [];
62
+ if (typeof existingSystem === "string" && existingSystem.trim()) {
63
+ parts.push(existingSystem.trim());
64
+ }
65
+ for (const context of contexts) {
66
+ if (!hasInjectedContext(existingSystem, context)) {
67
+ parts.push(context);
68
+ }
69
+ }
70
+ return parts.join("\n\n");
71
+ }
72
+ // END_BLOCK_SYSTEM_CONTEXT_FORMATTING
73
+ // START_BLOCK_PLUGIN_ENTRY
74
+ export const SystemContextInjectionPlugin = async () => {
75
+ const knownSubagents = createKnownSubagentSet();
76
+ return {
77
+ config: async (config) => {
78
+ syncConfiguredSubagents(config, knownSubagents);
79
+ },
80
+ "chat.message": async (_input, output) => {
81
+ if (!shouldInjectForAgent(output.message.agent, knownSubagents)) {
82
+ return;
83
+ }
84
+ output.message.system = appendSystemContexts(output.message.system, MAIN_SESSION_SYSTEM_CONTEXTS);
85
+ },
86
+ };
87
+ };
88
+ // END_BLOCK_PLUGIN_ENTRY
89
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/system-context-injection/index.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,iBAAiB;AACjB,wBAAwB;AACxB,sHAAsH;AACtH,mKAAmK;AACnK,8DAA8D;AAC9D,qEAAqE;AACrE,kBAAkB;AAClB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,0HAA0H;AAC1H,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,2HAA2H;AAC3H,qBAAqB;AAGrB,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,SAAS,CAAU,CAAC;AAC3D,MAAM,wBAAwB,GAAG,CAAC,UAAU,EAAE,iBAAiB,CAAU,CAAC;AAC1E,MAAM,uBAAuB,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAE5E,MAAM,4BAA4B,GAAG;IACnC;QACE,+BAA+B;QAC/B,+OAA+O;QAC/O,iDAAiD;QACjD,oHAAoH;QACpH,gCAAgC;KACjC,CAAC,IAAI,CAAC,IAAI,CAAC;CACJ,CAAC;AAMX,4BAA4B;AAC5B,SAAS,sBAAsB;IAC7B,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,kBAAkB,EAAE,GAAG,wBAAwB,EAAE,GAAG,sBAAsB,CAAC,CAAC,CAAC;AAClG,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAc,EAAE,cAA2B;IAC1E,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACpE,IAAK,UAA2C,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;YACtE,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,SAA6B,EAAE,cAA2B;IACtF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,uBAAuB,CAAC,QAAQ,CAAC,SAAqD,CAAC,EAAE,CAAC;QAC5F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AACD,0BAA0B;AAE1B,wCAAwC;AACxC,SAAS,kBAAkB,CAAC,cAAkC,EAAE,OAAe;IAC7E,OAAO,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,oBAAoB,CAC3B,cAAkC,EAClC,QAA2B;IAE3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AACD,sCAAsC;AAEtC,2BAA2B;AAC3B,MAAM,CAAC,MAAM,4BAA4B,GAAW,KAAK,IAAI,EAAE;IAC7D,MAAM,cAAc,GAAG,sBAAsB,EAAE,CAAC;IAEhD,OAAO;QACL,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACvB,uBAAuB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAClD,CAAC;QACD,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACvC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,EAAE,CAAC;gBAChE,OAAO;YACT,CAAC;YAED,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,oBAAoB,CAC1C,MAAM,CAAC,OAAO,CAAC,MAAM,EACrB,4BAA4B,CAC7B,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AACF,yBAAyB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osovv/vv-opencode",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Portable OpenCode workflow plugins, explicit memory, and CLI tooling.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -41,6 +41,10 @@
41
41
  "types": "./dist/plugins/memory/index.d.ts",
42
42
  "import": "./dist/plugins/memory/index.js"
43
43
  },
44
+ "./plugins/system-context-injection": {
45
+ "types": "./dist/plugins/system-context-injection/index.d.ts",
46
+ "import": "./dist/plugins/system-context-injection/index.js"
47
+ },
44
48
  "./plugins/secrets-redaction": {
45
49
  "types": "./dist/plugins/secrets-redaction/index.d.ts",
46
50
  "import": "./dist/plugins/secrets-redaction/index.js"
@@ -54,7 +58,7 @@
54
58
  "fmt:check": "oxfmt --check src",
55
59
  "test": "bun test",
56
60
  "check": "bun run typecheck && bun run lint && bun run fmt:check && bun test",
57
- "pack:check": "bun run build && bun -e \"const root = await import('./dist/index.js'); if (!('GuardianPlugin' in root)) throw new Error('dist root export missing GuardianPlugin'); if (!('MemoryPlugin' in root)) throw new Error('dist root export missing MemoryPlugin'); if (!('SecretsRedactionPlugin' in root)) throw new Error('dist root export missing SecretsRedactionPlugin'); await import('./dist/plugins/guardian/index.js'); await import('./dist/plugins/memory/index.js')\" && npm pack --dry-run",
61
+ "pack:check": "bun run build && bun -e \"const root = await import('./dist/index.js'); if (!('GuardianPlugin' in root)) throw new Error('dist root export missing GuardianPlugin'); if (!('MemoryPlugin' in root)) throw new Error('dist root export missing MemoryPlugin'); if (!('SystemContextInjectionPlugin' in root)) throw new Error('dist root export missing SystemContextInjectionPlugin'); if (!('SecretsRedactionPlugin' in root)) throw new Error('dist root export missing SecretsRedactionPlugin'); await import('./dist/plugins/guardian/index.js'); await import('./dist/plugins/memory/index.js'); await import('./dist/plugins/system-context-injection/index.js')\" && npm pack --dry-run",
58
62
  "prepare": "lefthook install --force"
59
63
  },
60
64
  "dependencies": {
@@ -20,6 +20,7 @@ Operating rules:
20
20
  - If the user says not to keep clarifying, finish with explicit assumptions instead of blocking.
21
21
  - Do not add requirements, scope, or constraints that the user did not ask for.
22
22
  - Do not include the raw request verbatim in the final XML unless the user explicitly asks for it.
23
+ - The final XML prompt must always be written in English.
23
24
  - Omit empty sections instead of emitting placeholders.
24
25
 
25
26
  XML rules: