sortie-dogs 0.10.12 → 0.10.13

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
@@ -50,7 +50,7 @@ two-level subagent depth to `.opencode/opencode.json`, preserving existing value
50
50
  ```json
51
51
  {
52
52
  "plugins": ["sortie-dogs"],
53
- "subagent_depth": 2
53
+ "experimental": { "subagent_depth": 2 }
54
54
  }
55
55
  ```
56
56
 
@@ -302,7 +302,7 @@ npm install --global sortie-dogs
302
302
  sortie-dogs init --global --profile v010
303
303
  ```
304
304
 
305
- Then add `sortie-dogs` and `subagent_depth: 2` to the global OpenCode config.
305
+ Then add `sortie-dogs` and `experimental.subagent_depth: 2` to the global OpenCode config.
306
306
  Global initialization installs assets only; it does not silently change the
307
307
  default agent or merge user settings.
308
308
 
@@ -3,5 +3,5 @@
3
3
  * installed project marker without importing every asset body.
4
4
  */
5
5
  export declare const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
6
- export declare const V010_RUNTIME_ASSET_VERSION = "0.10.0-v0912-language4-cost-rpt10-compaction-ref2-proposal1-review-remediation1-surface4-proposal-recovery2-quality1-terminal2-route1-path1-permission2-prerequisite1-v2-bridge1-intent1-reflection1-cancel1-proposal-budget1-goal-recovery1-delegate-execute1";
6
+ export declare const V010_RUNTIME_ASSET_VERSION = "0.10.0-v0912-language4-cost-rpt10-compaction-ref2-proposal1-review-remediation1-surface4-proposal-recovery2-quality1-terminal2-route1-path1-permission2-prerequisite1-v2-bridge1-intent1-reflection1-cancel1-proposal-budget1-goal-recovery1-delegate-execute1-v2-depth1-process-replacement1";
7
7
  export type RuntimeAssetVersion = typeof RUNTIME_ASSET_VERSION | typeof V010_RUNTIME_ASSET_VERSION;
@@ -3,4 +3,4 @@
3
3
  * installed project marker without importing every asset body.
4
4
  */
5
5
  export const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
6
- export const V010_RUNTIME_ASSET_VERSION = "0.10.0-v0912-language4-cost-rpt10-compaction-ref2-proposal1-review-remediation1-surface4-proposal-recovery2-quality1-terminal2-route1-path1-permission2-prerequisite1-v2-bridge1-intent1-reflection1-cancel1-proposal-budget1-goal-recovery1-delegate-execute1";
6
+ export const V010_RUNTIME_ASSET_VERSION = "0.10.0-v0912-language4-cost-rpt10-compaction-ref2-proposal1-review-remediation1-surface4-proposal-recovery2-quality1-terminal2-route1-path1-permission2-prerequisite1-v2-bridge1-intent1-reflection1-cancel1-proposal-budget1-goal-recovery1-delegate-execute1-v2-depth1-process-replacement1";
@@ -303,6 +303,7 @@ export declare class OperatorRuntime {
303
303
  observeChild(root: string, callID: string, childID: string): Promise<void>;
304
304
  private observeChildOnce;
305
305
  operatorReturned(root: string): Promise<OperatorState>;
306
+ processReplacementRequired(root: string, runID: string): Promise<OperatorState>;
306
307
  private operatorReturnedOnce;
307
308
  interrupted(root: string, reason: string): Promise<readonly string[]>;
308
309
  private interruptedOnce;
@@ -29,6 +29,7 @@ export class OperatorContractError extends Error {
29
29
  const OPERATOR_TASK_REFERENCE = "SORTIE_OPERATOR_TASK_REF";
30
30
  const OPERATOR_DELEGATE_TASK_REFERENCE = "SORTIE_OPERATOR_DELEGATE_REF";
31
31
  const REPAIR_VALIDATION_STALE_PROOF_DECISION = "operator-contract-repair-validation-incomplete:operator-recovery-proof-unavailable-or-stale";
32
+ const PROCESS_REPLACEMENT_DECISION = "operator-process-remediation-replacement-required";
32
33
  const ACCEPTANCE_REMEDIATION_DECISION = "operator-acceptance-remediation-required";
33
34
  const REVIEW_REMEDIATION_DECISION = "operator-review-remediation-required";
34
35
  const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
@@ -1407,6 +1408,17 @@ export class OperatorRuntime {
1407
1408
  operatorReturned(root) {
1408
1409
  return this.serial(root, () => this.operatorReturnedOnce(root));
1409
1410
  }
1411
+ processReplacementRequired(root, runID) {
1412
+ return this.serial(root, async () => {
1413
+ const state = await this.required(root);
1414
+ if (state.runID !== runID || state.phase !== "awaiting-decision" || state.decision !== "process-defect") {
1415
+ throw new Error("operator-process-remediation-replacement-not-ready");
1416
+ }
1417
+ state.decision = PROCESS_REPLACEMENT_DECISION;
1418
+ await this.save(state);
1419
+ return state;
1420
+ });
1421
+ }
1410
1422
  async operatorReturnedOnce(root) {
1411
1423
  const state = await this.required(root);
1412
1424
  if (state.phase === "running") {
@@ -1651,8 +1663,9 @@ export class OperatorRuntime {
1651
1663
  const repairValidationRetryAvailable = this.canRetryRepairValidation(state);
1652
1664
  const acceptanceRemediation = state.decision === ACCEPTANCE_REMEDIATION_DECISION;
1653
1665
  const reviewRemediation = state.decision === REVIEW_REMEDIATION_DECISION;
1666
+ const processReplacement = state.decision === PROCESS_REPLACEMENT_DECISION;
1654
1667
  const hostReconciliationRequired = state.phase === "awaiting-decision" && state.contractRepair === null &&
1655
- !repairValidationRetryAvailable && !acceptanceRemediation && !reviewRemediation;
1668
+ !repairValidationRetryAvailable && !acceptanceRemediation && !reviewRemediation && !processReplacement;
1656
1669
  const failedAcceptanceUnit = acceptanceRemediation
1657
1670
  ? state.units.find(unit => unit.status === "failed" && ["acceptance", "process-defect"].includes(unit.resultClass ?? "")) : undefined;
1658
1671
  const failedEvidence = failedAcceptanceUnit?.failure;
@@ -1725,6 +1738,9 @@ export class OperatorRuntime {
1725
1738
  ...(hostReconciliationRequired ? {
1726
1739
  next_action: `call ${this.profile.toolPrefix}resume_operator once with this run_id and acceptance_fingerprint; if it returns a Task, dispatch that exact Task in this turn`,
1727
1740
  } : {}),
1741
+ ...(processReplacement ? {
1742
+ next_action: `this immutable run is not resumable: call ${this.profile.toolPrefix}cancel_operator with reason=plain, then call ${this.profile.toolPrefix}prepare_operator for a replacement run under the same goal; copy this packet's acceptance array verbatim, retain consumed cumulative budget, and repair only the read, write, preparation, and validation contract required by that acceptance; do not call resume_operator again or claim evidence`,
1743
+ } : {}),
1728
1744
  ...(acceptanceRemediation || reviewRemediation ? { next_action: remediationNextAction } : {}),
1729
1745
  ...(state.repairResidualPaths.length === 0 ? {} : { repair_residual_paths: state.repairResidualPaths }),
1730
1746
  ...(state.phase === "cancelled" && state.decision === "operator-contract-repair-unavailable-after-cancel" &&
@@ -4,6 +4,9 @@ import { type CatalogModel } from "./model-routing.js";
4
4
  export declare function processRemediationReplacementPacket(code: string, packet: unknown, cancelTool: string, prepareTool: string): {
5
5
  status: string;
6
6
  code: string;
7
+ same_run_resumable: boolean;
8
+ replacement_preserves_goal: boolean;
9
+ cumulative_spend_resets: boolean;
7
10
  packet: unknown;
8
11
  next_action: string;
9
12
  };
@@ -39,10 +39,13 @@ const PREVIEW_ROUTES = Object.freeze([
39
39
  PREVIEW_REVIEW_ROUTE,
40
40
  ]);
41
41
  export function processRemediationReplacementPacket(code, packet, cancelTool, prepareTool) {
42
- return { status: "operator-process-remediation-replacement-required", code, packet,
43
- next_action: `Call ${cancelTool} with reason=plain, then call ${prepareTool} with the exact same ordered acceptance, ` +
44
- "the same unit and write scope, and the remaining cumulative budget. Do not call resume_operator again, " +
45
- "claim evidence, reset spend, or widen scope." };
42
+ const durable = record(packet) ? { ...packet, resume_requires_host_reconciliation: false,
43
+ next_action: `This immutable run is not resumable. Call ${cancelTool} with reason=plain, then call ${prepareTool} for a replacement run under the same goal.` } : packet;
44
+ return { status: "operator-process-remediation-replacement-required", code, same_run_resumable: false,
45
+ replacement_preserves_goal: true, cumulative_spend_resets: false, packet: durable,
46
+ next_action: `Call ${cancelTool} with reason=plain, then call ${prepareTool} for a replacement run under the same goal. ` +
47
+ "Copy the packet acceptance array byte-for-byte and retain cumulative spend. Repair only the read, write, preparation, and validation contract required by that acceptance. " +
48
+ "Do not call resume_operator again, claim evidence, or treat the replacement as a new goal." };
46
49
  }
47
50
  /**
48
51
  * Declare every preview route in the catalog, adding the variant to a listed model and the whole model
@@ -736,7 +739,8 @@ export function createProfiledPlugin(profile, assetVersion) {
736
739
  // A process defect without an authorized Git lifecycle has no committed remediation
737
740
  // baseline. Preserve the failed run and return an explicit replacement route instead
738
741
  // of turning this local routing limitation into a terminal tool exception.
739
- return JSON.stringify(processRemediationReplacementPacket(remediationError.message, operators.packet(state), cancel, prepare));
742
+ const replacement = await operators.processReplacementRequired(context.sessionID, state.runID);
743
+ return JSON.stringify(processRemediationReplacementPacket(remediationError.message, operators.packet(replacement), cancel, prepare));
740
744
  }
741
745
  }
742
746
  const retried = await operators.resumeRepairValidation(context.sessionID, state.runID, source => control.authorizeOperatorContractRepairValidationRetry(context.sessionID, { ...source, declarationFingerprint: goalFingerprint }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sortie-dogs",
3
- "version": "0.10.12",
3
+ "version": "0.10.13",
4
4
  "description": "Bounded agent harness and validated orchestration loop plugin for OpenCode",
5
5
  "keywords": [
6
6
  "opencode",