@mono-agent/agent-app 0.15.1 → 0.15.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.
Files changed (53) hide show
  1. package/README.md +4 -3
  2. package/dist/broadcast-recorder.d.ts +27 -0
  3. package/dist/broadcast-recorder.d.ts.map +1 -0
  4. package/dist/broadcast-recorder.js +104 -0
  5. package/dist/broadcast-recorder.js.map +1 -0
  6. package/dist/channel-drivers/live.d.ts +12 -0
  7. package/dist/channel-drivers/live.d.ts.map +1 -0
  8. package/dist/channel-drivers/live.js +48 -0
  9. package/dist/channel-drivers/live.js.map +1 -0
  10. package/dist/doctor.js +10 -12
  11. package/dist/doctor.js.map +1 -1
  12. package/dist/notify-runtime.d.ts +26 -0
  13. package/dist/notify-runtime.d.ts.map +1 -0
  14. package/dist/notify-runtime.js +27 -0
  15. package/dist/notify-runtime.js.map +1 -0
  16. package/dist/notify-tool.d.ts +51 -0
  17. package/dist/notify-tool.d.ts.map +1 -0
  18. package/dist/notify-tool.js +182 -0
  19. package/dist/notify-tool.js.map +1 -0
  20. package/dist/recipes/base.d.ts +15 -0
  21. package/dist/recipes/base.d.ts.map +1 -0
  22. package/dist/recipes/base.js +51 -0
  23. package/dist/recipes/base.js.map +1 -0
  24. package/dist/recipes/catalog.d.ts +4 -0
  25. package/dist/recipes/catalog.d.ts.map +1 -0
  26. package/dist/recipes/catalog.js +525 -0
  27. package/dist/recipes/catalog.js.map +1 -0
  28. package/dist/recipes/index.d.ts +11 -0
  29. package/dist/recipes/index.d.ts.map +1 -0
  30. package/dist/recipes/index.js +14 -0
  31. package/dist/recipes/index.js.map +1 -0
  32. package/dist/recipes/types.d.ts +70 -0
  33. package/dist/recipes/types.d.ts.map +1 -0
  34. package/dist/recipes/types.js +15 -0
  35. package/dist/recipes/types.js.map +1 -0
  36. package/dist/request-model-override.d.ts.map +1 -1
  37. package/dist/request-model-override.js +4 -5
  38. package/dist/request-model-override.js.map +1 -1
  39. package/dist/sessions-command.d.ts +53 -0
  40. package/dist/sessions-command.d.ts.map +1 -0
  41. package/dist/sessions-command.js +309 -0
  42. package/dist/sessions-command.js.map +1 -0
  43. package/dist/setup.d.ts +29 -0
  44. package/dist/setup.d.ts.map +1 -0
  45. package/dist/setup.js +97 -0
  46. package/dist/setup.js.map +1 -0
  47. package/dist/wizard/prompts.js +2 -2
  48. package/dist/wizard/prompts.js.map +1 -1
  49. package/dist/wizard/run.js +1 -4
  50. package/dist/wizard/run.js.map +1 -1
  51. package/package.json +15 -15
  52. package/skills/mono-agent-composer/references/config-blueprint.md +1 -1
  53. package/skills/mono-agent-composer/references/discovery-questions.md +1 -1
package/README.md CHANGED
@@ -309,16 +309,17 @@ stale auth locks are repaired only when the recorded process is securely proven
309
309
  gone. The
310
310
  wizard keeps **Allow all tools** as its default. Pi/Claude flows disclose
311
311
  shell/file/web/channel effects and reconfirm an unsandboxed choice. Direct Codex
312
- fixes policy to exact allow-all, uses its native network-off workspace sandbox,
312
+ fixes policy to effective allow-all (an omitted or wildcard-containing
313
+ allowlist with no denied tools), uses its native network-off workspace sandbox,
313
314
  denies unattended escalations, and fails unexpected server requests promptly.
314
315
  Mixed chains are unrestricted only under explicit `runtime.routeSafety:
315
316
  "per-route-native"`, which isolates provider runtimes and applies a documented
316
317
  route-local contract. The default `uniform` mode keeps one common monotonic
317
318
  contract and rejects/skips routes that cannot represent it. Pi keeps mono-agent
318
319
  tool policy and optional SRT; Claude uses representable provider-native controls;
319
- direct Codex/OpenCode use provider-native safety plus exact allow-all. No route
320
+ direct Codex/OpenCode use provider-native safety plus effective allow-all. No route
320
321
  silently drops a required capability. Pi `pi:opencode-go:*` remains a Pi route.
321
- Direct OpenCode also requires exact allow-all; restrictive static policies fail
322
+ Direct OpenCode has the same omitted-or-wildcard/empty-deny requirement; restrictive static policies fail
322
323
  validation/runtime and an incompatible dynamic override is warned and ignored.
323
324
 
324
325
  ### Run history
@@ -0,0 +1,27 @@
1
+ import type { RunEventSink } from "@mono-agent/agent-contracts";
2
+ import type { RunRecorder } from "@mono-agent/observability";
3
+ /** Stable run context stamped onto every broadcast frame. */
4
+ export interface BroadcastRunContext {
5
+ readonly runId: string;
6
+ readonly conversationId: string;
7
+ /** Producing instance's trace-source id (empty when the host has none). */
8
+ readonly sourceId: string;
9
+ readonly sourceLabel?: string;
10
+ /** Trigger channel, e.g. "cron" | "webhook" | "chat" | "memory". */
11
+ readonly source?: string;
12
+ /** Trigger detail (cron job id / webhook endpoint name). */
13
+ readonly sourceDetail?: string;
14
+ }
15
+ /**
16
+ * Wrap a {@link RunRecorder} so every run start/event/finish is ALSO published to
17
+ * a {@link RunEventSink} (the in-process live bus), giving operator surfaces
18
+ * sub-run visibility the on-disk recorder can't (it flushes only at start/finish).
19
+ *
20
+ * Broadcast is best-effort and additive, exactly like the Phoenix exporter path:
21
+ * the inner recorder is the source of truth for the returned summary, and a
22
+ * publish failure never changes the run outcome (publish is wrapped and the bus's
23
+ * own `publish` is contracted never to throw). `seq` is left 0 here — the bus
24
+ * stamps a process-wide monotonic value on publish.
25
+ */
26
+ export declare function createBroadcastRunRecorder(inner: RunRecorder, sink: RunEventSink, ctx: BroadcastRunContext): RunRecorder;
27
+ //# sourceMappingURL=broadcast-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broadcast-recorder.d.ts","sourceRoot":"","sources":["../src/broadcast-recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE/E,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,2BAA2B,CAAC;AAE9G,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,YAAY,EAClB,GAAG,EAAE,mBAAmB,GACvB,WAAW,CAyFb"}
@@ -0,0 +1,104 @@
1
+ import { LIVE_EVENT_SCHEMA } from "@mono-agent/agent-contracts";
2
+ import { redactJsonValue } from "@mono-agent/observability";
3
+ /**
4
+ * Wrap a {@link RunRecorder} so every run start/event/finish is ALSO published to
5
+ * a {@link RunEventSink} (the in-process live bus), giving operator surfaces
6
+ * sub-run visibility the on-disk recorder can't (it flushes only at start/finish).
7
+ *
8
+ * Broadcast is best-effort and additive, exactly like the Phoenix exporter path:
9
+ * the inner recorder is the source of truth for the returned summary, and a
10
+ * publish failure never changes the run outcome (publish is wrapped and the bus's
11
+ * own `publish` is contracted never to throw). `seq` is left 0 here — the bus
12
+ * stamps a process-wide monotonic value on publish.
13
+ */
14
+ export function createBroadcastRunRecorder(inner, sink, ctx) {
15
+ let eventIndex = 0;
16
+ let terminalStarted = false;
17
+ let terminalPromise;
18
+ const publish = (frame) => {
19
+ try {
20
+ sink.publish(frame);
21
+ }
22
+ catch {
23
+ // Broadcast is best-effort; a sink failure must never break the run.
24
+ }
25
+ };
26
+ const finished = async (summary) => {
27
+ const redactedSummary = redactJsonValue(summary);
28
+ publish({
29
+ t: "run_finished",
30
+ schema: LIVE_EVENT_SCHEMA,
31
+ sourceId: ctx.sourceId,
32
+ runId: ctx.runId,
33
+ status: redactedSummary.status,
34
+ summary: redactedSummary,
35
+ seq: 0,
36
+ });
37
+ return summary;
38
+ };
39
+ const recorder = {
40
+ onEvent(event) {
41
+ // Terminal is a hard boundary in the live protocol. Events accepted after
42
+ // commit starts could otherwise appear after `run_finished` or be absent
43
+ // from the authoritative summary/export.
44
+ if (terminalStarted)
45
+ return;
46
+ inner.onEvent(event);
47
+ const redactedEvent = redactJsonValue(event);
48
+ publish({
49
+ t: "event",
50
+ schema: LIVE_EVENT_SCHEMA,
51
+ sourceId: ctx.sourceId,
52
+ runId: ctx.runId,
53
+ eventIndex: eventIndex++,
54
+ event: redactedEvent,
55
+ seq: 0,
56
+ });
57
+ },
58
+ async prepareFinish(result) {
59
+ await inner.prepareFinish?.(result);
60
+ },
61
+ async commitFinish(result) {
62
+ if (terminalPromise === undefined) {
63
+ terminalStarted = true;
64
+ terminalPromise = (async () => await finished(inner.commitFinish === undefined ? await inner.finish(result) : await inner.commitFinish(result)))();
65
+ }
66
+ return await terminalPromise;
67
+ },
68
+ async finish(result) {
69
+ await recorder.prepareFinish?.(result);
70
+ return await recorder.commitFinish(result);
71
+ },
72
+ async fail(error) {
73
+ if (terminalPromise === undefined) {
74
+ terminalStarted = true;
75
+ terminalPromise = (async () => await finished(await inner.fail(error)))();
76
+ }
77
+ return await terminalPromise;
78
+ },
79
+ };
80
+ // `start` is optional on RunRecorder — only expose (and emit run_started) when
81
+ // the inner recorder has one, so callers that probe `recorder.start?.()` behave
82
+ // identically to the unwrapped recorder.
83
+ if (inner.start !== undefined) {
84
+ const innerStart = inner.start.bind(inner);
85
+ recorder.start = async () => {
86
+ const summary = await innerStart();
87
+ publish({
88
+ t: "run_started",
89
+ schema: LIVE_EVENT_SCHEMA,
90
+ sourceId: ctx.sourceId,
91
+ ...(ctx.sourceLabel === undefined ? {} : { sourceLabel: ctx.sourceLabel }),
92
+ runId: ctx.runId,
93
+ conversationId: ctx.conversationId,
94
+ ...(ctx.source === undefined ? {} : { source: ctx.source }),
95
+ ...(ctx.sourceDetail === undefined ? {} : { sourceDetail: ctx.sourceDetail }),
96
+ startedAt: summary.startedAt ?? new Date().toISOString(),
97
+ seq: 0,
98
+ });
99
+ return summary;
100
+ };
101
+ }
102
+ return recorder;
103
+ }
104
+ //# sourceMappingURL=broadcast-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broadcast-recorder.js","sourceRoot":"","sources":["../src/broadcast-recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { LiveAdapterConfig, LiveAdapterHandle, LiveAdapterOptions } from "@mono-agent/operator-adapter";
2
+ import type { ChannelDriver } from "../channels.js";
3
+ export interface LiveChannelOverrides {
4
+ readonly adapterFactory?: (options: LiveAdapterOptions) => Promise<LiveAdapterHandle>;
5
+ }
6
+ /**
7
+ * The live event relay is enabled by default on loopback so read-only operator
8
+ * surfaces (the `@mono-agent/session-web` PWA) can observe a running agent
9
+ * without a per-agent config edit.
10
+ */
11
+ export declare function createLiveChannelDriver(overrides?: LiveChannelOverrides): ChannelDriver<LiveAdapterConfig>;
12
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/channel-drivers/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQpD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACvF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,GAAE,oBAAyB,GACnC,aAAa,CAAC,iBAAiB,CAAC,CAsClC"}
@@ -0,0 +1,48 @@
1
+ import { buildChannelConfigView } from "../channel-config-view.js";
2
+ let liveModule;
3
+ const loadLiveModule = async () => (liveModule ??= await import("@mono-agent/operator-adapter"));
4
+ /**
5
+ * The live event relay is enabled by default on loopback so read-only operator
6
+ * surfaces (the `@mono-agent/session-web` PWA) can observe a running agent
7
+ * without a per-agent config edit.
8
+ */
9
+ export function createLiveChannelDriver(overrides = {}) {
10
+ return {
11
+ id: "live",
12
+ label: "Live",
13
+ async configView(input) {
14
+ const adapter = await loadLiveModule();
15
+ return await buildChannelConfigView(this, adapter.LIVE_CONFIG_FIELDS, input, { jsonKey: "live" });
16
+ },
17
+ async loadConfig(input) {
18
+ const adapter = await loadLiveModule();
19
+ return await adapter.loadLiveAdapterConfig({ env: input.env, jsonPath: input.configPath });
20
+ },
21
+ isConfigError(error) {
22
+ return liveModule !== undefined && error instanceof liveModule.LiveAdapterError;
23
+ },
24
+ disabledReason(config) {
25
+ return config.enabled ? undefined : "Live event relay is disabled.";
26
+ },
27
+ async start(input) {
28
+ const adapterModule = await loadLiveModule();
29
+ const adapterFactory = overrides.adapterFactory ?? adapterModule.startLiveAdapter;
30
+ const bus = input.liveEventBus ?? adapterModule.createLiveEventBus();
31
+ const adapter = await adapterFactory({
32
+ bus,
33
+ host: input.config.host,
34
+ port: input.config.port,
35
+ basePath: input.config.basePath,
36
+ allowNonLoopback: input.config.allowNonLoopback,
37
+ ...(input.config.apiKey === undefined ? {} : { apiKey: input.config.apiKey }),
38
+ onServerError: (reason) => input.onFailure(reason),
39
+ ...(input.logger === undefined ? {} : { logger: input.logger }),
40
+ });
41
+ return {
42
+ summary: { baseUrl: adapter.baseUrl },
43
+ stop: () => adapter.stop(),
44
+ };
45
+ },
46
+ };
47
+ }
48
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/channel-drivers/live.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAKnE,IAAI,UAAyC,CAAC;AAC9C,MAAM,cAAc,GAAG,KAAK,IAAgC,EAAE,CAC5D,CAAC,UAAU,KAAK,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC,CAAC;AAMhE;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,YAAkC,EAAE;IAEpC,OAAO;QACL,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,MAAM;QACb,KAAK,CAAC,UAAU,CAAC,KAAK;YACpB,MAAM,OAAO,GAAG,MAAM,cAAc,EAAE,CAAC;YACvC,OAAO,MAAM,sBAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,kBAAkB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACpG,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,KAAK;YACpB,MAAM,OAAO,GAAG,MAAM,cAAc,EAAE,CAAC;YACvC,OAAO,MAAM,OAAO,CAAC,qBAAqB,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7F,CAAC;QACD,aAAa,CAAC,KAAK;YACjB,OAAO,UAAU,KAAK,SAAS,IAAI,KAAK,YAAY,UAAU,CAAC,gBAAgB,CAAC;QAClF,CAAC;QACD,cAAc,CAAC,MAAM;YACnB,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,+BAA+B,CAAC;QACtE,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,KAAK;YACf,MAAM,aAAa,GAAG,MAAM,cAAc,EAAE,CAAC;YAC7C,MAAM,cAAc,GAAG,SAAS,CAAC,cAAc,IAAI,aAAa,CAAC,gBAAgB,CAAC;YAClF,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,IAAI,aAAa,CAAC,kBAAkB,EAAE,CAAC;YACrE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC;gBACnC,GAAG;gBACH,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI;gBACvB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI;gBACvB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;gBAC/B,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,gBAAgB;gBAC/C,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC7E,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC;gBAClD,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;aAChE,CAAC,CAAC;YACH,OAAO;gBACL,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;gBACrC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE;aAC3B,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/doctor.js CHANGED
@@ -234,7 +234,7 @@ async function applyRequestModelOverrideCompatibilityChecks(sections, config, dr
234
234
  const skillBypasses = [];
235
235
  const piModelResolutionFailures = [];
236
236
  const monoSandboxActive = config.sandbox !== undefined && config.sandbox.mode !== "off";
237
- const restrictiveToolPolicy = !hasExactAllowAllToolPolicy(config.tools);
237
+ const restrictiveToolPolicy = !hasAllowAllOnlyToolPolicy(config.tools);
238
238
  let configuredMcpServerNames = [];
239
239
  if (config.tools.mcpConfigPath !== undefined) {
240
240
  try {
@@ -354,7 +354,7 @@ async function applyRequestModelOverrideCompatibilityChecks(sections, config, dr
354
354
  ...(toolPolicyBypasses.length === 0
355
355
  ? []
356
356
  : [
357
- "Per-trigger direct OpenCode model overrides require exact allow-all because OpenCode's provider-owned tool loop does not consume mono-agent allowedTools/disallowedTools.",
357
+ "Per-trigger direct OpenCode model overrides require an effective allow-all policy because OpenCode's provider-owned tool loop does not consume mono-agent allowedTools/disallowedTools.",
358
358
  ...toolPolicyBypasses,
359
359
  ]),
360
360
  ...(effortBypasses.length === 0
@@ -393,10 +393,8 @@ async function applyRequestModelOverrideCompatibilityChecks(sections, config, dr
393
393
  function isUnknownRecord(value) {
394
394
  return typeof value === "object" && value !== null && !Array.isArray(value);
395
395
  }
396
- function hasExactAllowAllToolPolicy(tools) {
397
- return tools.allowedTools.length === 1
398
- && tools.allowedTools[0] === "*"
399
- && tools.disallowedTools.length === 0;
396
+ function hasAllowAllOnlyToolPolicy(tools) {
397
+ return isAllowAllTools(tools.allowedTools) && tools.disallowedTools.length === 0;
400
398
  }
401
399
  /** Adapter send tools each channel owns; an allowed entry needs BOTH the tool AND the enabled channel. */
402
400
  const CHANNEL_OWNED_SEND_TOOLS = {
@@ -1660,22 +1658,22 @@ async function toolsSection(config, input) {
1660
1658
  ]
1661
1659
  .filter(({ model, executionMode }) => model.sdk === "claude" && executionMode === "cli")
1662
1660
  .map(({ model }) => referenceOf(model));
1663
- const exactAllowAll = hasExactAllowAllToolPolicy(config.tools);
1661
+ const allowAllOnly = hasAllowAllOnlyToolPolicy(config.tools);
1664
1662
  const dedicatedNoToolsProbe = input.codexNoToolsProbe === true
1665
1663
  && allowedTools.length === 0
1666
1664
  && config.tools.disallowedTools.length === 0;
1667
1665
  if (directCodexModels.length > 0
1668
1666
  && !dedicatedNoToolsProbe
1669
- && !exactAllowAll) {
1667
+ && !allowAllOnly) {
1670
1668
  status = "error";
1671
1669
  details.push(`Direct Codex model${directCodexModels.length === 1 ? "" : "s"} ${directCodexModels.join(", ")} cannot enforce ` +
1672
- "tools.allowedTools/tools.disallowedTools. Use exact allow-all (allowedTools: [\"*\"] with no disallowedTools), " +
1670
+ "tools.allowedTools/tools.disallowedTools. Use allow-all-only (allowedTools omitted or containing \"*\", with no disallowedTools), " +
1673
1671
  "or select a runtime that supports restrictive tool policies.");
1674
1672
  }
1675
- if (directOpenCodeModels.length > 0 && !exactAllowAll) {
1673
+ if (directOpenCodeModels.length > 0 && !allowAllOnly) {
1676
1674
  status = "error";
1677
1675
  details.push(`Direct OpenCode model${directOpenCodeModels.length === 1 ? "" : "s"} ${directOpenCodeModels.join(", ")} cannot enforce ` +
1678
- "tools.allowedTools/tools.disallowedTools. Use exact allow-all (allowedTools: [\"*\"] with no disallowedTools), " +
1676
+ "tools.allowedTools/tools.disallowedTools. Use allow-all-only (allowedTools omitted or containing \"*\", with no disallowedTools), " +
1679
1677
  "or use a Pi runtime (including pi:opencode-go:*).");
1680
1678
  }
1681
1679
  if (claudeCliModels.length > 0 && allowedTools.length === 0) {
@@ -2836,7 +2834,7 @@ function routeNativeSafetyDetail(model, index, config) {
2836
2834
  if (model.sdk === "codex") {
2837
2835
  return `${label} ${ref}: ${directCodexSandboxPosture(config.runtime.permissionMode).detail}`;
2838
2836
  }
2839
- return `${label} ${ref}: OpenCode provider-owned execution with exact allow-all tool policy applies; mono-agent SRT rules are not projected.`;
2837
+ return `${label} ${ref}: OpenCode provider-owned execution with an effective allow-all tool policy applies; mono-agent SRT rules are not projected.`;
2840
2838
  }
2841
2839
  function directCodexSandboxPosture(permissionMode) {
2842
2840
  if (permissionMode === "bypassPermissions") {