@fro.bot/systematic 3.16.3 → 3.16.4

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/cli.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { type CapabilityClock, type CapabilityOutputSink, type ConfigObservationMetadata } from './lib/capability-snapshot.js';
3
- interface CapabilityCliRoots {
3
+ export interface CapabilityCliRoots {
4
4
  readonly agentsRoot: string;
5
5
  readonly cwd: string;
6
6
  readonly homeDir: string;
package/dist/index.js CHANGED
@@ -11803,7 +11803,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
11803
11803
  result.satisfiedCount = source.debug.satisfiedCount;
11804
11804
  result.missingCount = source.debug.missingCount;
11805
11805
  result.family = source.debug.family;
11806
- result.status = source.debug.status;
11806
+ result.debugEpochStatus = source.debug.status;
11807
11807
  }
11808
11808
  return result;
11809
11809
  }
@@ -11845,10 +11845,12 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
11845
11845
  function writeCompletionResult(output, result, target) {
11846
11846
  if (!isRecord7(output))
11847
11847
  return;
11848
+ const existingMetadata = isRecord7(output.metadata) ? output.metadata : {};
11848
11849
  if (result.status === "completed" || result.status === "duplicate") {
11849
11850
  output.title = "Workflow transition completed";
11850
11851
  output.output = `workflow guard completed ${target}`;
11851
11852
  output.metadata = {
11853
+ ...existingMetadata,
11852
11854
  ...metadata2(),
11853
11855
  workflowGuard: { status: "completed", target }
11854
11856
  };
@@ -11862,6 +11864,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
11862
11864
  reasonCode
11863
11865
  });
11864
11866
  output.metadata = {
11867
+ ...existingMetadata,
11865
11868
  ...metadata2(),
11866
11869
  workflowGuard: {
11867
11870
  status: resultStatus,
@@ -11870,6 +11873,19 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
11870
11873
  }
11871
11874
  };
11872
11875
  }
11876
+ function writeAbandonedCompletionResult(output, target, reasonCode) {
11877
+ writeCompletionResult(output, { target, status: "unavailable", reasonCode }, target);
11878
+ }
11879
+ function writeAbandonedCompletionMetadata(output, target, reasonCode) {
11880
+ if (!isRecord7(output))
11881
+ return;
11882
+ const existingMetadata = isRecord7(output.metadata) ? output.metadata : {};
11883
+ output.metadata = {
11884
+ ...existingMetadata,
11885
+ ...metadata2(),
11886
+ workflowGuard: { status: "unavailable", target, reasonCode }
11887
+ };
11888
+ }
11873
11889
  function prepareSkill(host, args2) {
11874
11890
  const skill = normalizeSkill(host.tool, args2);
11875
11891
  if (!skill)
@@ -12286,6 +12302,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
12286
12302
  callId: pending.callID,
12287
12303
  transitionId: pending.transitionId
12288
12304
  });
12305
+ writeAbandonedCompletionMetadata(output, pending.target, "failed-operation");
12289
12306
  return;
12290
12307
  }
12291
12308
  const result = guard.finalizeTransition({
@@ -12440,19 +12457,32 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
12440
12457
  }
12441
12458
  return readbacks;
12442
12459
  }
12460
+ function finishMismatchedTarget(callDigest, pending, output) {
12461
+ abandonComplete(callDigest, pending, false);
12462
+ markUnavailable();
12463
+ writeAbandonedCompletionResult(output, pending.target, "invalid-transition");
12464
+ }
12465
+ function finishUnreplayableComplete(finalTarget, output) {
12466
+ markUnavailable();
12467
+ writeAbandonedCompletionResult(output, finalTarget ?? "unit", "guard-unavailable");
12468
+ }
12469
+ function finishUnavailableReadback(callDigest, pending, output) {
12470
+ abandonComplete(callDigest, pending, true);
12471
+ markUnavailable();
12472
+ writeAbandonedCompletionResult(output, pending.target, "finalization-failed");
12473
+ }
12443
12474
  async function finishComplete(host, output) {
12444
12475
  const callDigest = digestCall(ledger, host.callID);
12445
12476
  const pending = pendingCompletes.get(callDigest);
12446
12477
  const finalTarget = normalizeTarget(host.args);
12447
12478
  if (pending && (!finalTarget || finalTarget !== pending.target)) {
12448
- abandonComplete(callDigest, pending, false);
12449
- markUnavailable();
12479
+ finishMismatchedTarget(callDigest, pending, output);
12450
12480
  return;
12451
12481
  }
12452
12482
  if (!pending) {
12453
12483
  if (replayTerminalComplete(callDigest, finalTarget, output))
12454
12484
  return;
12455
- markUnavailable();
12485
+ finishUnreplayableComplete(finalTarget, output);
12456
12486
  return;
12457
12487
  }
12458
12488
  if (!options.observer) {
@@ -12461,8 +12491,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
12461
12491
  }
12462
12492
  const readbacks = await completionReadbacks();
12463
12493
  if (readbacks.status === "unavailable") {
12464
- abandonComplete(callDigest, pending, true);
12465
- markUnavailable();
12494
+ finishUnavailableReadback(callDigest, pending, output);
12466
12495
  return;
12467
12496
  }
12468
12497
  finalizeComplete(callDigest, pending, output, readbacks.status === "ready" ? readbacks.readbacks : undefined);
@@ -1,4 +1,6 @@
1
1
  import type { Config } from '@opencode-ai/plugin';
2
+ import type { AgentConfig } from '@opencode-ai/sdk';
3
+ import { type PermissionSetting } from './validation.js';
2
4
  export interface ConfigHandlerDeps {
3
5
  directory: string;
4
6
  bundledSkillsDir: string;
@@ -11,6 +13,41 @@ export interface ConfigHandlerDeps {
11
13
  }
12
14
  export declare function toTitleCase(name: string): string;
13
15
  export declare function formatAgentDescription(name: string, description: string | undefined): string;
16
+ /**
17
+ * Per-tool permission rule map as actually emitted by {@link permissionFromRules}:
18
+ * each key is a match pattern (`'*'` or an exact name) mapped to a setting.
19
+ */
20
+ export type AgentPermissionRuleMap = Record<string, PermissionSetting>;
21
+ /**
22
+ * Agent permission shape as emitted onto `AgentConfig.permission`, narrowed at
23
+ * this module's boundary to include `skill`. The `@opencode-ai/sdk` v1 `Config`
24
+ * type this module targets omits `skill` from `AgentConfig['permission']`
25
+ * (it only appears on the SDK's v2 `PermissionRuleConfig` surface), but
26
+ * `applyPermissionOverlay`/`addManagedSkillRules` genuinely write a `skill`
27
+ * rule map identical in shape to `bash`. This type documents and reads that
28
+ * real runtime shape without migrating the module to the v2 type surface.
29
+ *
30
+ * `permissionFromRules` emits a rule map for whatever tool key gets passed to
31
+ * `setPermissionRule` — not just the named keys below (e.g. `task`, per
32
+ * `PermissionConfig` in validation.ts and the `task` overlay field applied at
33
+ * config-handler.ts's overlay pass). The named keys stay for documentation of
34
+ * the common cases; the index signature covers every other emitted tool key.
35
+ */
36
+ export interface EmittedAgentPermission {
37
+ edit?: AgentPermissionRuleMap;
38
+ bash?: AgentPermissionRuleMap;
39
+ webfetch?: AgentPermissionRuleMap;
40
+ doom_loop?: AgentPermissionRuleMap;
41
+ external_directory?: AgentPermissionRuleMap;
42
+ skill?: AgentPermissionRuleMap;
43
+ readonly [tool: string]: AgentPermissionRuleMap | undefined;
44
+ }
45
+ /**
46
+ * Read an agent's emitted permission map, narrowed to include `skill` (see
47
+ * {@link EmittedAgentPermission}). Use this instead of `AgentConfig['permission']`
48
+ * when a caller needs to observe the `skill` rule map this module writes.
49
+ */
50
+ export declare function readEmittedAgentPermission(agent: AgentConfig | undefined): EmittedAgentPermission | undefined;
14
51
  /**
15
52
  * Create the config hook handler for the Systematic plugin.
16
53
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fro.bot/systematic",
3
- "version": "3.16.3",
3
+ "version": "3.16.4",
4
4
  "description": "Compound-engineering loops for OpenCode, Pi, and Claude Code",
5
5
  "type": "module",
6
6
  "homepage": "https://fro.bot/systematic",
@@ -40,6 +40,8 @@
40
40
  "test:integration": "bun test tests/integration",
41
41
  "test:all": "bun test",
42
42
  "typecheck": "tsc --noEmit",
43
+ "typecheck:scripts": "tsc -p tsconfig.scripts.json",
44
+ "typecheck:all": "tsc -p tsconfig.tests.json",
43
45
  "lint": "biome check .",
44
46
  "fix": "bun run lint --fix",
45
47
  "docs:dev": "bun run --cwd docs dev",
@@ -93,10 +95,10 @@
93
95
  }
94
96
  },
95
97
  "devDependencies": {
96
- "@biomejs/biome": "2.5.11",
98
+ "@biomejs/biome": "2.5.12",
97
99
  "@earendil-works/pi-coding-agent": "0.83.0",
98
- "@opencode-ai/plugin": "1.18.21",
99
- "@opencode-ai/sdk": "1.18.21",
100
+ "@opencode-ai/plugin": "1.18.27",
101
+ "@opencode-ai/sdk": "1.18.27",
100
102
  "@semantic-release/exec": "7.1.0",
101
103
  "@tintinweb/pi-subagents": "0.14.3",
102
104
  "@types/bun": "latest",