orizu 0.5.39 → 0.5.40

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 (85) hide show
  1. package/README.md +77 -0
  2. package/dist/dataset-commands.d.ts +3 -1
  3. package/dist/dataset-commands.d.ts.map +1 -1
  4. package/dist/dataset-commands.js +101 -62
  5. package/dist/dataset-delete-workflow.d.ts +4 -0
  6. package/dist/dataset-delete-workflow.d.ts.map +1 -0
  7. package/dist/dataset-delete-workflow.js +75 -0
  8. package/dist/dataset-lock-workflow.d.ts +12 -0
  9. package/dist/dataset-lock-workflow.d.ts.map +1 -0
  10. package/dist/dataset-lock-workflow.js +76 -0
  11. package/dist/dataset-readme-workflow.d.ts +13 -0
  12. package/dist/dataset-readme-workflow.d.ts.map +1 -0
  13. package/dist/dataset-readme-workflow.js +82 -0
  14. package/dist/dataset-row-workflow.d.ts +14 -0
  15. package/dist/dataset-row-workflow.d.ts.map +1 -0
  16. package/dist/dataset-row-workflow.js +202 -0
  17. package/dist/dataset-split-reads.d.ts +28 -0
  18. package/dist/dataset-split-reads.d.ts.map +1 -0
  19. package/dist/dataset-split-reads.js +47 -0
  20. package/dist/help.d.ts.map +1 -1
  21. package/dist/help.js +29 -3
  22. package/dist/hosted-boot.d.ts +1 -0
  23. package/dist/hosted-boot.d.ts.map +1 -1
  24. package/dist/hosted-boot.js +17 -0
  25. package/dist/hosted-harness-opencode.d.ts +4 -5
  26. package/dist/hosted-harness-opencode.d.ts.map +1 -1
  27. package/dist/hosted-harness-opencode.js +66 -52
  28. package/dist/hosted-loop-lifecycle.d.ts +4 -10
  29. package/dist/hosted-loop-lifecycle.d.ts.map +1 -1
  30. package/dist/hosted-loop-lifecycle.js +4 -10
  31. package/dist/hosted-loop.d.ts +2 -0
  32. package/dist/hosted-loop.d.ts.map +1 -1
  33. package/dist/hosted-loop.js +5 -4
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +9 -1
  36. package/dist/instruction-delivery.d.ts +14 -0
  37. package/dist/instruction-delivery.d.ts.map +1 -0
  38. package/dist/instruction-delivery.js +103 -0
  39. package/dist/instruction-set-sync/index.d.ts +17 -0
  40. package/dist/instruction-set-sync/index.d.ts.map +1 -1
  41. package/dist/instruction-set-sync/index.js +44 -17
  42. package/dist/instruction-set-update/index.d.ts +2 -2
  43. package/dist/instruction-set-update/index.d.ts.map +1 -1
  44. package/dist/instruction-set-update/index.js +2 -2
  45. package/dist/instruction-sets-cli.d.ts.map +1 -1
  46. package/dist/instruction-sets-cli.js +19 -27
  47. package/dist/json-response.d.ts +1 -0
  48. package/dist/json-response.d.ts.map +1 -1
  49. package/dist/json-response.js +7 -0
  50. package/dist/preview-runtime.d.ts +2 -2
  51. package/dist/preview-runtime.d.ts.map +1 -1
  52. package/dist/preview-runtime.js +37 -7
  53. package/dist/task-export-workflow.d.ts +4 -0
  54. package/dist/task-export-workflow.d.ts.map +1 -0
  55. package/dist/task-export-workflow.js +46 -0
  56. package/dist/workbench-cli.js +1 -1
  57. package/package.json +1 -1
  58. package/src/dataset-commands.ts +92 -92
  59. package/src/dataset-delete-workflow.ts +72 -0
  60. package/src/dataset-lock-workflow.ts +74 -0
  61. package/src/dataset-readme-workflow.ts +80 -0
  62. package/src/dataset-row-workflow.ts +248 -0
  63. package/src/dataset-split-reads.ts +43 -0
  64. package/src/help.ts +29 -3
  65. package/src/hosted-boot.ts +16 -1
  66. package/src/hosted-harness-opencode.ts +67 -65
  67. package/src/hosted-loop-lifecycle.ts +4 -10
  68. package/src/hosted-loop.ts +6 -4
  69. package/src/hosted-model-cache.d.mts +2 -0
  70. package/src/hosted-model-cache.mjs +53 -0
  71. package/src/index.ts +10 -0
  72. package/src/instruction-delivery.ts +123 -0
  73. package/src/instruction-set-sync/index.ts +61 -14
  74. package/src/instruction-set-update/index.ts +4 -3
  75. package/src/instruction-sets-cli.ts +19 -27
  76. package/src/json-response.ts +8 -0
  77. package/src/preview-runtime.ts +40 -10
  78. package/src/task-export-workflow.ts +56 -0
  79. package/src/workbench-cli.ts +1 -1
  80. package/vendor/skills/orizu/references/cli-reference.md +34 -0
  81. package/vendor/skills/orizu/references/dataset-design.md +1 -1
  82. package/dist/dataset-edit-rows.d.ts +0 -10
  83. package/dist/dataset-edit-rows.d.ts.map +0 -1
  84. package/dist/dataset-edit-rows.js +0 -90
  85. package/src/dataset-edit-rows.ts +0 -124
@@ -49,8 +49,9 @@
49
49
  * would break both ports and must be re-verified.
50
50
  */
51
51
  import { readFileSync } from 'fs';
52
+ import { refreshHostedModels } from '../src/hosted-model-cache.mjs';
52
53
  import { HOSTED_AGENT_NAME, HOSTED_AGENT_PROMPT } from './hosted-agent-prompt.js';
53
- import { findProvider, parseModelIdentity } from './provider-registry.js';
54
+ import { parseModelIdentity } from './provider-registry.js';
54
55
  import { HARNESS_NAMES } from './hosted-harness.js';
55
56
  // OpenCode is HARD-PINNED to this version everywhere it is installed/launched.
56
57
  // AUDIT RISK #1 (SSE fragility): the entire event model rides OpenCode's
@@ -116,16 +117,6 @@ export function ascendingId(prefix, nowMs = Date.now()) {
116
117
  const hex = encoded.toString(16).padStart(12, '0');
117
118
  return `${prefix}_${hex}${randomBase62(14)}`;
118
119
  }
119
- // -- Anthropic / OpenAI reasoning-effort mapping (port of bridge.py) ---------
120
- const ANTHROPIC_THINKING_BUDGETS = { high: 16_000, max: 31_999 };
121
- const ANTHROPIC_ADAPTIVE_THINKING_MODELS = new Set([
122
- 'claude-fable-5',
123
- 'claude-opus-4-6',
124
- 'claude-opus-4-7',
125
- 'claude-opus-4-8',
126
- 'claude-sonnet-4-6',
127
- ]);
128
- const ANTHROPIC_ADAPTIVE_EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'max']);
129
120
  /**
130
121
  * Split a possibly provider-qualified model string into provider + model id,
131
122
  * through THE registry parse (`parseModelIdentity`, ORI-2031): the provider is
@@ -158,35 +149,14 @@ export function buildPromptRequestBody(content, model, opencodeMessageId, reason
158
149
  // Shared parse (see qualifyHostedModel): keeps the prompt path and the
159
150
  // ALI-1086 pre-prompt validation in lockstep by construction.
160
151
  const { providerId, modelId } = qualifyHostedModel(model);
161
- const modelSpec = { providerID: providerId, modelID: modelId };
162
- // Reasoning options are a property of the WIRE PROTOCOL, not of a provider
163
- // name (ORI-2031 row 7). `openai-chat` gets no options at all — identical to
164
- // today's fall-through for any provider the driver does not recognise, and
165
- // honest: Orizu has never measured chat-completions reasoning fields
166
- // (ORI-2032). A bare model id still resolves through qualifyHostedModel's
167
- // 'anthropic' default, so its options are unchanged.
168
- const protocol = findProvider(providerId)?.protocol ?? null;
169
- if (reasoningEffort) {
170
- if (protocol === 'anthropic-messages') {
171
- if (ANTHROPIC_ADAPTIVE_THINKING_MODELS.has(modelId)) {
172
- const options = { thinking: { type: 'adaptive' } };
173
- if (ANTHROPIC_ADAPTIVE_EFFORTS.has(reasoningEffort)) {
174
- options.outputConfig = { effort: reasoningEffort };
175
- }
176
- modelSpec.options = options;
177
- }
178
- else {
179
- const budget = ANTHROPIC_THINKING_BUDGETS[reasoningEffort];
180
- if (budget !== undefined) {
181
- modelSpec.options = { thinking: { type: 'enabled', budgetTokens: budget } };
182
- }
183
- }
184
- }
185
- else if (protocol === 'openai-responses') {
186
- modelSpec.options = { reasoningEffort, reasoningSummary: 'auto' };
187
- }
188
- }
189
- body.model = modelSpec;
152
+ body.model = { providerID: providerId, modelID: modelId };
153
+ // Reasoning effort travels as the top-level `variant` (ORI-2526). OpenCode's
154
+ // prompt body accepts only providerID/modelID inside `model` and silently
155
+ // dropped the options we used to send there. Each model's variants map the
156
+ // effort onto its own request fields; an effort the model has no variant for
157
+ // is ignored by OpenCode, so no per-provider mapping lives here.
158
+ if (reasoningEffort)
159
+ body.variant = reasoningEffort;
190
160
  return body;
191
161
  }
192
162
  // -- OpenCode part → HarnessEvent transform (port of _transform_part_to_event) -
@@ -506,6 +476,8 @@ export function createOpenCodeHarness(options) {
506
476
  const userMessageIds = new Set([opencodeMessageId]);
507
477
  const pendingParts = new Map();
508
478
  const emittedToolStates = new Set();
479
+ const partTypes = new Map();
480
+ const untypedDeltas = new Map();
509
481
  const handlePart = (part, delta) => {
510
482
  const partType = typeof part.type === 'string' ? part.type : '';
511
483
  const partId = typeof part.id === 'string' ? part.id : '';
@@ -710,18 +682,56 @@ export function createOpenCodeHarness(options) {
710
682
  }
711
683
  }
712
684
  }
713
- else if (eventType === 'message.part.updated') {
714
- const part = asRecord(props.part);
715
- const delta = props.delta;
716
- const ocMsgId = typeof part.messageID === 'string' ? part.messageID : '';
717
- if (allowedAssistantMsgIds.has(ocMsgId)) {
718
- for (const ev of handlePart(part, delta))
719
- yield ev;
685
+ else if (eventType === 'message.part.updated' || eventType === 'message.part.delta') {
686
+ // Word-by-word text arrives as `message.part.delta` (ORI-2525), which
687
+ // names the part but not its type. Reasoning parts send deltas too,
688
+ // so a delta streams only once its part is known to be text. A delta
689
+ // can overtake its part's announcement (opencode #26924); it waits
690
+ // here until the announcement says what the part is.
691
+ const updates = [];
692
+ if (eventType === 'message.part.updated') {
693
+ const part = asRecord(props.part);
694
+ const partId = typeof part.id === 'string' ? part.id : '';
695
+ updates.push({ part, delta: props.delta });
696
+ if (partId && typeof part.type === 'string')
697
+ partTypes.set(partId, part.type);
698
+ const early = untypedDeltas.get(partId);
699
+ if (early) {
700
+ untypedDeltas.delete(partId);
701
+ const announced = typeof part.text === 'string' ? part.text : '';
702
+ // Replay unless the announced text already includes them.
703
+ if (part.type === 'text' && !announced.startsWith(early.join(''))) {
704
+ for (const delta of early) {
705
+ updates.push({ part: { type: 'text', id: partId, messageID: part.messageID }, delta });
706
+ }
707
+ }
708
+ }
720
709
  }
721
- else if (ocMsgId) {
722
- const list = pendingParts.get(ocMsgId) ?? [];
723
- list.push({ part, delta });
724
- pendingParts.set(ocMsgId, list);
710
+ else {
711
+ const partId = typeof props.partID === 'string' ? props.partID : '';
712
+ const delta = props.delta;
713
+ if (props.field !== 'text' || !partId || typeof delta !== 'string')
714
+ continue;
715
+ const partType = partTypes.get(partId);
716
+ if (partType === undefined) {
717
+ untypedDeltas.set(partId, [...(untypedDeltas.get(partId) ?? []), delta]);
718
+ continue;
719
+ }
720
+ if (partType !== 'text')
721
+ continue;
722
+ updates.push({ part: { type: 'text', id: partId, messageID: props.messageID }, delta });
723
+ }
724
+ for (const { part, delta } of updates) {
725
+ const ocMsgId = typeof part.messageID === 'string' ? part.messageID : '';
726
+ if (allowedAssistantMsgIds.has(ocMsgId)) {
727
+ for (const ev of handlePart(part, delta))
728
+ yield ev;
729
+ }
730
+ else if (ocMsgId) {
731
+ const list = pendingParts.get(ocMsgId) ?? [];
732
+ list.push({ part, delta });
733
+ pendingParts.set(ocMsgId, list);
734
+ }
725
735
  }
726
736
  }
727
737
  else if (eventType === 'session.compacted') {
@@ -895,7 +905,7 @@ const MODEL_RESOLVE_TIMEOUT_MS = 30_000;
895
905
  const MODEL_RESOLVE_POLL_MS = 2_000;
896
906
  /**
897
907
  * Decide whether the requested model is resolvable by the RUNNING opencode,
898
- * polling briefly so the boot-time models.dev refresh has time to land.
908
+ * polling briefly for catalog readiness or transient server failures.
899
909
  * Fail-open on validator infrastructure, with a DELIBERATE asymmetry on null
900
910
  * catalog reads:
901
911
  * - null BEFORE any successful read → `skipped` immediately (dead/absent
@@ -1029,7 +1039,11 @@ export async function spawnOpenCode(opts) {
1029
1039
  const env = {
1030
1040
  OPENCODE_CONFIG_CONTENT: buildOpenCodeConfigContent(opts),
1031
1041
  ...(opts.env ?? {}),
1042
+ OPENCODE_DISABLE_MODELS_FETCH: '1',
1032
1043
  };
1044
+ const model = qualifyHostedModel(opts.model);
1045
+ env.OPENCODE_MODELS_PATH = await refreshHostedModels({ env: { ...process.env, ...env }, required: [`${model.providerId}/${model.modelId}`], fetchImpl: opts.fetchImpl, signal: opts.signal });
1046
+ opts.signal?.throwIfAborted();
1033
1047
  const cmd = ['opencode', 'serve', '--port', String(port)];
1034
1048
  const spawnImpl = opts.spawn ??
1035
1049
  ((command, spawnOpts) => {
@@ -31,16 +31,10 @@ import type { HostedSessionOrigin } from './hosted-runtime-assets.js';
31
31
  *
32
32
  * PIN CONSTRAINT: the hosted OpenCode runtime is HARD-PINNED to
33
33
  * `opencode-ai@1.14.41` (`OPENCODE_PINNED_VERSION`, SSE-fragile — do not bump)
34
- * whose BUNDLED model catalog predates this model (newest bundled anthropic
35
- * opus: claude-opus-4-7). Verified empirically on ALI-1086: 1.14.41 DOES fetch
36
- * `https://models.dev/api.json` at boot when reachable (cached to
37
- * `~/.cache/opencode/models.json`, refreshed when stale, disabled only by
38
- * `OPENCODE_DISABLE_MODELS_FETCH`), so with models.dev on the sandbox egress
39
- * allowlist (#1392, `ORIZU_HOSTED_EGRESS_ALLOWLIST`) this id resolves in new
40
- * sandboxes. If the catalog fetch is blocked/stale anyway, the loop's
41
- * pre-prompt validation (`awaitOpenCodeModelResolvable`) fails the run fast,
42
- * naming the resolvable alternatives. The durable fix for the stale bundled
43
- * catalog is the ALI-929 harness swap.
34
+ * whose bundled catalog predates this model. Images bake a validated models.dev
35
+ * list into the runtime user's cache. Orizu refreshes that cache before spawning
36
+ * OpenCode, preserving baked models on failure; the native unchecked writer is
37
+ * disabled (ORI-2513). Pre-prompt validation still checks the running server.
44
38
  */
45
39
  export declare const DEFAULT_HOSTED_MODEL = "anthropic/claude-opus-4-8";
46
40
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"hosted-loop-lifecycle.d.ts","sourceRoot":"","sources":["../src/hosted-loop-lifecycle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hosted-loop-lifecycle.d.ts","sourceRoot":"","sources":["../src/hosted-loop-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -29,16 +29,10 @@
29
29
  *
30
30
  * PIN CONSTRAINT: the hosted OpenCode runtime is HARD-PINNED to
31
31
  * `opencode-ai@1.14.41` (`OPENCODE_PINNED_VERSION`, SSE-fragile — do not bump)
32
- * whose BUNDLED model catalog predates this model (newest bundled anthropic
33
- * opus: claude-opus-4-7). Verified empirically on ALI-1086: 1.14.41 DOES fetch
34
- * `https://models.dev/api.json` at boot when reachable (cached to
35
- * `~/.cache/opencode/models.json`, refreshed when stale, disabled only by
36
- * `OPENCODE_DISABLE_MODELS_FETCH`), so with models.dev on the sandbox egress
37
- * allowlist (#1392, `ORIZU_HOSTED_EGRESS_ALLOWLIST`) this id resolves in new
38
- * sandboxes. If the catalog fetch is blocked/stale anyway, the loop's
39
- * pre-prompt validation (`awaitOpenCodeModelResolvable`) fails the run fast,
40
- * naming the resolvable alternatives. The durable fix for the stale bundled
41
- * catalog is the ALI-929 harness swap.
32
+ * whose bundled catalog predates this model. Images bake a validated models.dev
33
+ * list into the runtime user's cache. Orizu refreshes that cache before spawning
34
+ * OpenCode, preserving baked models on failure; the native unchecked writer is
35
+ * disabled (ORI-2513). Pre-prompt validation still checks the running server.
42
36
  */
43
37
  export const DEFAULT_HOSTED_MODEL = 'anthropic/claude-opus-4-8';
44
38
  /**
@@ -159,6 +159,8 @@ export interface RunHostedLoopOptions {
159
159
  /** Value-free local diagnostics shared with the event sink. Production routes
160
160
  * this through hosted-boot's stderr seam; consumer failures are ignored. */
161
161
  onDiagnostic?: (message: string) => void;
162
+ /** Report genuine harness activity to the session's progress watchdog. */
163
+ onProgress?: () => Promise<void>;
162
164
  }
163
165
  export interface HostedLoopResult {
164
166
  status: TerminalStatus;
@@ -1 +1 @@
1
- {"version":3,"file":"hosted-loop.d.ts","sourceRoot":"","sources":["../src/hosted-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAOH,OAAO,EAAyB,KAAK,YAAY,EAAyC,MAAM,qBAAqB,CAAA;AAQrH,OAAO,EAAoB,KAAK,WAAW,EAAuB,MAAM,qBAAqB,CAAA;AAE7F,OAAO,EAOL,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAA;AAIrC,OAAO,EAML,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAOL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAA;AAKnC,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,4BAA4B,CAAA;AACnC,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,4BAA4B,CAAA;AAOnC,eAAO,MAAM,wBAAwB,QAAgB,CAAA;AAErD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKrF;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,uBAAuB;IAC/B,OAAO,EAAE,YAAY,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,eAAe,GAAG,IAAI,CAAA;IAC/B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;IAC1H,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,wBAAwB,CAAA;IACjC,OAAO,EAAE,uBAAuB,CAAA;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,iBAAiB,CAAA;IAC1B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,uBAAuB,CAAA;IACvC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;yEACqE;IACrE,cAAc,CAAC,EAAE,MAAM,MAAM,CAAA;IAC7B,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,WAAW,CAAA;IACvB;2FACuF;IACvF,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,YAAY,CAAA;IAC7F;gFAC4E;IAC5E,mBAAmB,CAAC,EAAE,MAAM,YAAY,CAAA;IACxC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC1F,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IAC9C;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAA;IAC9F,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB;sDACkD;IAClD,eAAe,CAAC,EAAE,WAAW,CAAA;IAC7B,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC;;kFAE8E;IAC9E,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAC1D;;oDAEgD;IAChD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAA;IAChG;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;+DAC2D;IAC3D,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzC;iFAC6E;IAC7E,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAA;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAeD;;;;;iDAKiD;AACjD,eAAO,MAAM,6BAA6B,QAAiB,CAAA;AAa3D;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,EAAE,SAAS,MAAM,EAAmB,CAAA;AAKlF;;;;;;GAMG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AA+E/D,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAgiBzF;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC,CAalC;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,uBAAuB,EAChC,IAAI,EAAE,qBAAqB,EAC3B,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,SAAS,GAAG,YAAY,GAAG,eAAe,CAAC,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GACvG,OAAO,CAAC,gBAAgB,CAAC,CAe3B;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5F;AAID,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAyCD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,mBAAmB,GACtB,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
1
+ {"version":3,"file":"hosted-loop.d.ts","sourceRoot":"","sources":["../src/hosted-loop.ts"],"names":[],"mappings":"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"}
@@ -460,10 +460,9 @@ export async function runHostedLoop(opts) {
460
460
  }
461
461
  // Fail-fast model validation (ALI-1086): ask the RUNNING opencode whether
462
462
  // the requested model is resolvable BEFORE the first prompt. The pinned
463
- // opencode's bundled catalog is stale (predates claude-opus-4-8) and only
464
- // a boot-time models.dev fetch (#1392 allowlists it) refreshes it — when
465
- // that fetch is blocked, the first prompt used to die inside the SSE
466
- // stream with an opaque `run_failed: Model not found`. Now the run fails
463
+ // image catalog is baked and refreshed before spawn (ORI-2513). A model
464
+ // absent from that validated list still needs a clear error rather than
465
+ // dying inside the SSE stream with an opaque Model not found. The run fails
467
466
  // immediately with a structured artifact + an error naming the requested
468
467
  // id AND the resolvable alternatives. Fail-open on validator
469
468
  // infrastructure: an unreachable catalog endpoint (`skipped`) proceeds
@@ -612,6 +611,8 @@ export async function runHostedLoop(opts) {
612
611
  }
613
612
  return;
614
613
  }
614
+ if (event.kind !== 'question_auto_answered')
615
+ await opts.onProgress?.();
615
616
  yield event;
616
617
  }
617
618
  // A signal already durable before prompt startup can make a driver end
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsLA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAEhE,eAAO,MAAM,wBAAwB,GAAI,iBAAiB,MAAM;;;EACJ,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AA4tCtD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CA0B1G;AAED,eAAO,MAAM,iBAAiB,SAAU,CAAA;AACxC,eAAO,MAAM,uBAAuB,QAAkB,CAAA;AACtD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAexH;AAmMD,wBAAsB,IAAI,CAAC,OAAO,WAAwB,iBAyhBzD;AA6DD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEhF,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAwLA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAEhE,eAAO,MAAM,wBAAwB,GAAI,iBAAiB,MAAM;;;EACJ,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AA4tCtD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CA0B1G;AAED,eAAO,MAAM,iBAAiB,SAAU,CAAA;AACxC,eAAO,MAAM,uBAAuB,QAAkB,CAAA;AACtD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAexH;AAmMD,wBAAsB,IAAI,CAAC,OAAO,WAAwB,iBAiiBzD;AA6DD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEhF,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -52,7 +52,7 @@ import { acceptScoreRunCommand } from './scores-accept-cli.js';
52
52
  import { exportOptimizationRunCommand } from './optimization-export-cli.js';
53
53
  import { listOptimizationRunsCommand } from './optimizations-list-cli.js';
54
54
  import { promoteOptimizationCommand } from './optimizations-promote-cli.js';
55
- import { uploadDataset, listDatasets, pushDataset, downloadDataset, appendDatasetRows, setDatasetReadme, createDatasetVersion, createDatasetSplitSet, editDatasetRows, deleteDatasetRows, deleteDataset, lockDataset, cloneDataset, downloadAnnotations, } from './dataset-commands.js';
55
+ import { uploadDataset, listDatasets, pushDataset, downloadDataset, appendDatasetRows, setDatasetReadme, createDatasetVersion, createDatasetSplitSet, listDatasetSplitSets, showDatasetSplitSet, editDatasetRows, deleteDatasetRows, deleteDataset, lockDataset, cloneDataset, downloadAnnotations, } from './dataset-commands.js';
56
56
  import { workbenchCommand } from './workbench-cli.js';
57
57
  import { workspaceSyncCommand } from './workspace-sync.js';
58
58
  import { runGitCredentialInvocation } from './git-credential.js';
@@ -1664,6 +1664,14 @@ export async function main(rawArgs = process.argv.slice(2)) {
1664
1664
  await createDatasetVersion();
1665
1665
  return;
1666
1666
  }
1667
+ if (command === 'datasets' && subcommand === 'splits' && datasetsAction === 'list') {
1668
+ await listDatasetSplitSets();
1669
+ return;
1670
+ }
1671
+ if (command === 'datasets' && subcommand === 'splits' && datasetsAction === 'show') {
1672
+ await showDatasetSplitSet();
1673
+ return;
1674
+ }
1667
1675
  if (command === 'datasets' && subcommand === 'splits' && datasetsAction === 'create') {
1668
1676
  await createDatasetSplitSet();
1669
1677
  return;
@@ -0,0 +1,14 @@
1
+ import { type SyncDiskOptions, type SyncDiskResult, type SyncPayload, type SyncRequestPlan } from './instruction-set-sync/index.js';
2
+ import { type UpdatePlan, type UpdateResult } from './instruction-set-update/index.js';
3
+ export interface Interrupted {
4
+ interrupted: 130 | 143;
5
+ }
6
+ export declare function syncInstructionSet(out: string, project: string, plan: SyncRequestPlan, options: SyncDiskOptions): Promise<Interrupted | {
7
+ payload: SyncPayload;
8
+ result: SyncDiskResult;
9
+ }>;
10
+ export declare function updateInstructionSets(out: string, project: string, isApproved: boolean, noSync: boolean): Promise<{
11
+ plan: UpdatePlan;
12
+ result: UpdateResult;
13
+ } | Interrupted>;
14
+ //# sourceMappingURL=instruction-delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-delivery.d.ts","sourceRoot":"","sources":["../src/instruction-delivery.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0D,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAC3L,OAAO,EAAsE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAK1J,MAAM,WAAW,WAAW;IAAG,WAAW,EAAE,GAAG,GAAG,GAAG,CAAA;CAAE;AAkEvD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,eAAe;;;GAM/G;AAED,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG,WAAW,CAAC,CAiCnE"}
@@ -0,0 +1,103 @@
1
+ import { Cause, Effect, Exit } from 'effect';
2
+ import { authedFetch } from './http.js';
3
+ import { responsePayload } from './json-response.js';
4
+ import { stageSyncPayload, startSyncLockClaim, tryClaimSyncLock } from './instruction-set-sync/index.js';
5
+ import { applyUpdate, lockedProfileIdentity, makeUpdatePlan, readUpdateLock } from './instruction-set-update/index.js';
6
+ // Existing file steps throw plain errors; keep them as the failure value so the
7
+ // CLI prints exactly the same message.
8
+ const attempt = (operation) => Effect.try({ try: operation, catch: cause => cause });
9
+ function readPayload(path, action) {
10
+ return Effect.tryPromise({
11
+ // The body stays unchecked here, as before: stageSyncPayload and makeUpdatePlan validate it.
12
+ // SAFETY: their existing error messages for malformed bodies are part of the CLI's output.
13
+ try: async (signal) => await responsePayload(await authedFetch(path, { method: 'GET', signal }), action),
14
+ catch: cause => cause,
15
+ });
16
+ }
17
+ // Waiting for another process's lock is the only interruptible part: nothing
18
+ // is held yet. Publishing runs to completion once the lock is ours.
19
+ function holdSyncLock(appRoot, use) {
20
+ const acquire = Effect.gen(function* () {
21
+ const claim = yield* attempt(() => startSyncLockClaim(appRoot));
22
+ while (true) {
23
+ const claimed = yield* attempt(() => tryClaimSyncLock(claim));
24
+ if (typeof claimed === 'function')
25
+ return claimed;
26
+ yield* Effect.interruptible(Effect.sleep(claimed));
27
+ }
28
+ });
29
+ return Effect.acquireUseRelease(acquire, () => use, release => Effect.sync(release));
30
+ }
31
+ // Stage the version, publish it under the lock, and always remove an
32
+ // unpublished stage, including after Ctrl-C or SIGTERM.
33
+ function deliverPayload(...args) {
34
+ return Effect.acquireUseRelease(attempt(() => stageSyncPayload(...args)), staged => holdSyncLock(staged.appRoot, attempt(staged.publish)).pipe(Effect.map(warnings => ({ destination: staged.destination, wasPresent: staged.wasPresent, warnings }))), staged => Effect.sync(staged.discard));
35
+ }
36
+ async function runOrThrow(program, signal) {
37
+ const exit = await Effect.runPromiseExit(program, { signal });
38
+ if (Exit.isSuccess(exit))
39
+ return exit.value;
40
+ throw Cause.squash(exit.cause);
41
+ }
42
+ // `once`: a second signal falls through to Node's default kill.
43
+ async function runDelivery(program) {
44
+ const controller = new AbortController();
45
+ let interrupted;
46
+ const handleInterrupt = () => { interrupted ??= 130; controller.abort(); };
47
+ const handleTerminate = () => { interrupted ??= 143; controller.abort(); };
48
+ process.once('SIGINT', handleInterrupt);
49
+ process.once('SIGTERM', handleTerminate);
50
+ try {
51
+ return await runOrThrow(program(controller.signal), controller.signal);
52
+ }
53
+ catch (error) {
54
+ if (interrupted !== undefined)
55
+ return { interrupted };
56
+ throw error;
57
+ }
58
+ finally {
59
+ process.removeListener('SIGINT', handleInterrupt);
60
+ process.removeListener('SIGTERM', handleTerminate);
61
+ }
62
+ }
63
+ export function syncInstructionSet(out, project, plan, options) {
64
+ return runDelivery(() => Effect.gen(function* () {
65
+ const payload = yield* readPayload(plan.path, 'Instruction sets sync');
66
+ const result = yield* deliverPayload(out, project, plan, payload, options);
67
+ return { payload, result };
68
+ }));
69
+ }
70
+ export function updateInstructionSets(out, project, isApproved, noSync) {
71
+ const program = (signal) => Effect.gen(function* () {
72
+ const lock = yield* attempt(() => readUpdateLock(out, project));
73
+ const payloads = [];
74
+ for (const [setSlug, set] of Object.entries(lock.instructionSets)) {
75
+ const barePath = `/api/cli/instruction-sets/${encodeURIComponent(setSlug)}/sync?project=${encodeURIComponent(project)}`;
76
+ payloads.push(yield* readPayload(barePath, 'Instruction sets update'));
77
+ for (const profileSlugValue of Object.keys(set.profiles)) {
78
+ const identity = yield* attempt(() => lockedProfileIdentity(out, setSlug, profileSlugValue));
79
+ const query = new URLSearchParams({ project, profile: identity });
80
+ const path = `/api/cli/instruction-sets/${encodeURIComponent(setSlug)}/sync?${query.toString()}`;
81
+ payloads.push(yield* readPayload(path, 'Instruction sets update'));
82
+ }
83
+ }
84
+ const plan = yield* attempt(() => makeUpdatePlan(project, lock, payloads));
85
+ if (!isApproved)
86
+ return { plan, result: { absent: [], warnings: [] } };
87
+ // applyUpdate's own steps are not interruptible; each version it syncs is
88
+ // a nested delivery that the shared signal interrupts and cleans up.
89
+ const result = yield* Effect.uninterruptible(Effect.tryPromise({
90
+ try: () => applyUpdate(out, project, plan, noSync, undefined, (...args) => runOrThrow(deliverPayload(...args), signal)),
91
+ catch: cause => cause,
92
+ }));
93
+ return { plan, result };
94
+ });
95
+ // --no-sync stages nothing to clean up, so keep Node's default signal
96
+ // handling: a signal stops it at once instead of being held until the
97
+ // update has already landed.
98
+ if (noSync) {
99
+ const signal = new AbortController().signal;
100
+ return runOrThrow(program(signal), signal);
101
+ }
102
+ return runDelivery(program);
103
+ }
@@ -44,6 +44,13 @@ export declare function planSyncRequest(reference: string, versionFlag: string |
44
44
  export declare function canonicalVersionDigest(components: Record<string, string>, settings: Record<string, unknown>): string;
45
45
  export declare function recordResolvedPayloadInLock(lock: InstructionSetLockV1, payload: SyncPayload, now?: () => Date): InstructionSetLockV1;
46
46
  export declare function renderGeneratedVersionModule(components: Record<string, string>, manifest: unknown): string;
47
+ export interface SyncLockClaim {
48
+ lockPath: string;
49
+ metadata: string;
50
+ deadline: number;
51
+ }
52
+ export declare function startSyncLockClaim(appRoot: string): SyncLockClaim;
53
+ export declare function tryClaimSyncLock({ lockPath, metadata, deadline }: SyncLockClaim): (() => void) | number;
47
54
  export declare function withSyncLock<T>(appRoot: string, operation: () => T): T;
48
55
  export interface SyncDiskResult {
49
56
  destination: string;
@@ -57,5 +64,15 @@ export interface SyncDiskOptions {
57
64
  target?: SyncTarget;
58
65
  platform?: NodeJS.Platform;
59
66
  }
67
+ export interface StagedSync {
68
+ appRoot: string;
69
+ destination: string;
70
+ wasPresent: boolean;
71
+ /** Publishes the staged version; the caller must hold the folder lock. Returns warnings. */
72
+ publish: () => string[];
73
+ /** Removes the staged version if it was not published. Safe to call more than once. */
74
+ discard: () => void;
75
+ }
60
76
  export declare function syncPayloadToDisk(out: string, project: string, plan: SyncRequestPlan, payload: SyncPayload, options?: SyncDiskOptions): SyncDiskResult;
77
+ export declare function stageSyncPayload(out: string, project: string, plan: SyncRequestPlan, payload: SyncPayload, options?: SyncDiskOptions): StagedSync;
61
78
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/instruction-set-sync/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/instruction-set-sync/index.ts"],"names":[],"mappings":"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"}
@@ -411,12 +411,18 @@ function removeObservedSyncLock(lockPath, observed) {
411
411
  console.warn(`instruction_set_sync_lock_stale_removed:${lockPath}`);
412
412
  return true;
413
413
  }
414
- export function withSyncLock(appRoot, operation) {
414
+ export function startSyncLockClaim(appRoot) {
415
415
  mkdirSync(appRoot, { recursive: true });
416
- const lockPath = join(appRoot, '.orizu.lock.json.lock');
417
- const metadata = `${JSON.stringify({ pid: process.pid, createdAt: new Date().toISOString() })}\n`;
418
416
  const lockWaitMs = processTestMilliseconds('ORIZU_TEST_SYNC_LOCK_WAIT_MS', 100, SYNC_LOCK_WAIT_MS) ?? SYNC_LOCK_WAIT_MS;
419
- const deadline = Date.now() + lockWaitMs;
417
+ return {
418
+ lockPath: join(appRoot, '.orizu.lock.json.lock'),
419
+ metadata: `${JSON.stringify({ pid: process.pid, createdAt: new Date().toISOString() })}\n`,
420
+ deadline: Date.now() + lockWaitMs,
421
+ };
422
+ }
423
+ // One claim attempt: returns the release function, or how long to wait before
424
+ // trying again. Waiting is the caller's job so it can be blocking or not.
425
+ export function tryClaimSyncLock({ lockPath, metadata, deadline }) {
420
426
  while (true) {
421
427
  try {
422
428
  writeFileSync(lockPath, metadata, { encoding: 'utf8', flag: 'wx', mode: 0o600 });
@@ -442,10 +448,10 @@ export function withSyncLock(appRoot, operation) {
442
448
  if (Date.now() >= deadline) {
443
449
  throw new Error(`instruction_set_sync_lock_busy${busyPid === undefined ? '' : `:${busyPid}`}`);
444
450
  }
445
- sleepSync(Math.min(SYNC_LOCK_RETRY_MS, Math.max(1, deadline - Date.now())));
451
+ return Math.min(SYNC_LOCK_RETRY_MS, Math.max(1, deadline - Date.now()));
446
452
  }
447
453
  }
448
- const release = () => {
454
+ return () => {
449
455
  try {
450
456
  if (readFileSync(lockPath, 'utf8') === metadata)
451
457
  rmSync(lockPath);
@@ -455,6 +461,14 @@ export function withSyncLock(appRoot, operation) {
455
461
  throw error;
456
462
  }
457
463
  };
464
+ }
465
+ export function withSyncLock(appRoot, operation) {
466
+ const claim = startSyncLockClaim(appRoot);
467
+ let release = tryClaimSyncLock(claim);
468
+ while (typeof release === 'number') {
469
+ sleepSync(release);
470
+ release = tryClaimSyncLock(claim);
471
+ }
458
472
  let result;
459
473
  try {
460
474
  result = operation();
@@ -490,6 +504,16 @@ function holdForProcessTest(name) {
490
504
  sleepSync(milliseconds);
491
505
  }
492
506
  export function syncPayloadToDisk(out, project, plan, payload, options = {}) {
507
+ const staged = stageSyncPayload(out, project, plan, payload, options);
508
+ try {
509
+ const warnings = withSyncLock(staged.appRoot, staged.publish);
510
+ return { destination: staged.destination, wasPresent: staged.wasPresent, warnings };
511
+ }
512
+ finally {
513
+ staged.discard();
514
+ }
515
+ }
516
+ export function stageSyncPayload(out, project, plan, payload, options = {}) {
493
517
  const target = parseSyncTarget(options.target);
494
518
  const now = options.now ?? (() => new Date());
495
519
  const set = payload.instructionSet;
@@ -605,9 +629,11 @@ export function syncPayloadToDisk(out, project, plan, payload, options = {}) {
605
629
  else {
606
630
  assertExistingVersionMatches(destination, componentHashes, manifestBytes, generatedBytes);
607
631
  }
608
- let warnings = [];
609
- try {
610
- withSyncLock(appRoot, () => {
632
+ return {
633
+ appRoot,
634
+ destination,
635
+ wasPresent,
636
+ publish: () => {
611
637
  holdForProcessTest('ORIZU_TEST_SYNC_HOLD_BEFORE_PUBLISH_MS');
612
638
  const currentLock = readLock(appRoot, project);
613
639
  holdForProcessTest('ORIZU_TEST_SYNC_HOLD_LOCK_MS');
@@ -671,8 +697,9 @@ export function syncPayloadToDisk(out, project, plan, payload, options = {}) {
671
697
  }
672
698
  stagedTemp = null;
673
699
  }
674
- warnings = emitManagedArtifacts(out, appRoot, currentLock, options.forceHelpers ?? false, target, journal);
700
+ const warnings = emitManagedArtifacts(out, appRoot, currentLock, options.forceHelpers ?? false, target, journal);
675
701
  journal.write(join(appRoot, 'orizu.lock.json'), serializeLock(currentLock));
702
+ return warnings;
676
703
  }
677
704
  catch (error) {
678
705
  journal.rollback();
@@ -688,11 +715,11 @@ export function syncPayloadToDisk(out, project, plan, payload, options = {}) {
688
715
  }
689
716
  throw error;
690
717
  }
691
- });
692
- }
693
- finally {
694
- if (stagedTemp)
695
- rmSync(stagedTemp, { recursive: true, force: true });
696
- }
697
- return { destination, wasPresent, warnings };
718
+ },
719
+ discard: () => {
720
+ if (stagedTemp)
721
+ rmSync(stagedTemp, { recursive: true, force: true });
722
+ stagedTemp = null;
723
+ },
724
+ };
698
725
  }
@@ -1,5 +1,5 @@
1
1
  import { type InstructionSetLockV1 } from '../instruction-set-lock/index.js';
2
- import { type SyncPayload } from '../instruction-set-sync/index.js';
2
+ import { syncPayloadToDisk, type SyncDiskResult, type SyncPayload } from '../instruction-set-sync/index.js';
3
3
  export interface UpdateResolution {
4
4
  payload: SyncPayload;
5
5
  profileIdentity: string;
@@ -16,7 +16,7 @@ export interface UpdateResult {
16
16
  absent: string[];
17
17
  warnings: string[];
18
18
  }
19
- export declare function applyUpdate(out: string, project: string, plan: UpdatePlan, noSync: boolean, now?: () => Date): Promise<UpdateResult>;
19
+ export declare function applyUpdate(out: string, project: string, plan: UpdatePlan, noSync: boolean, now?: () => Date, sync?: (...args: Parameters<typeof syncPayloadToDisk>) => SyncDiskResult | Promise<SyncDiskResult>): Promise<UpdateResult>;
20
20
  export interface PrunePlan {
21
21
  lock: InstructionSetLockV1;
22
22
  removals: Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/instruction-set-update/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EAA6E,KAAK,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAG9I,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAMD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,CAIlF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAmCpG;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,oBAAoB,EAC1B,QAAQ,EAAE,WAAW,EAAE,GACtB,UAAU,CAiDZ;AA8CD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AA2CD,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,OAAO,EACf,GAAG,GAAE,MAAM,IAAuB,GACjC,OAAO,CAAC,YAAY,CAAC,CA4DvB;AAMD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,oBAAoB,CAAA;IAC1B,QAAQ,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAC5F;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;gBAEjB,OAAO,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAA;KAAE,CAAC;CAQjF;AAyBD,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAiEzF;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC,CAAA;CAC/B;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAmFlH"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/instruction-set-update/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EAA4C,iBAAiB,EAAgB,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAGnK,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAMD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,CAIlF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAmCpG;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,oBAAoB,EAC1B,QAAQ,EAAE,WAAW,EAAE,GACtB,UAAU,CAiDZ;AA8CD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AA2CD,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,OAAO,EACf,GAAG,GAAE,MAAM,IAAuB,EAClC,IAAI,GAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,KAAK,cAAc,GAAG,OAAO,CAAC,cAAc,CAAqB,GACpH,OAAO,CAAC,YAAY,CAAC,CA4DvB;AAMD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,oBAAoB,CAAA;IAC1B,QAAQ,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAC5F;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;gBAEjB,OAAO,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAA;KAAE,CAAC;CAQjF;AAyBD,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAiEzF;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC,CAAA;CAC/B;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAmFlH"}