@rulvar/planner 1.11.0 → 1.12.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CompiledWorkflow, Ctx, Engine, InMemoryStore, JournalEntry, Json, ModelSpec, RunHandle, ScriptRejected, ScriptRunner } from "@rulvar/core";
1
+ import { CompiledWorkflow, Ctx, Engine, InMemoryStore, JournalEntry, Json, ModelSpec, RunHandle, RunOptions, ScriptRejected, ScriptRunner } from "@rulvar/core";
2
2
 
3
3
  //#region src/compile.d.ts
4
4
  /**
@@ -49,6 +49,30 @@ interface PlanOptions {
49
49
  profiles?: string[];
50
50
  /** Self-repair rounds from JSON diagnostics; default 3 (Appendix A). */
51
51
  repairRounds?: number;
52
+ /**
53
+ * Run options of the planning conversation itself, applied at GENESIS
54
+ * only: the first plan() of a goal starts the journal with them, and
55
+ * budgetUsd becomes the run's immutable ceiling B0, recorded in
56
+ * RunMeta. A later plan() of the same goal resumes the existing
57
+ * journal under its RECORDED ceiling: a differing explicit budgetUsd
58
+ * warns (RULVAR_PLAN_BUDGET_DRIFT) and never tops up or replaces the
59
+ * frozen value, and limits/deadlineAt/signal do not apply to a
60
+ * resumed journal (core resume semantics; cancel through the handle).
61
+ * The runId stays goal-derived (planRunIdOf) and is not overridable.
62
+ * Absent options, the planning run is UNBOUNDED, as before.
63
+ */
64
+ run?: Pick<RunOptions, "budgetUsd" | "limits" | "deadlineAt" | "signal">;
65
+ }
66
+ interface RunPlannedOptions {
67
+ /** Options of the planning conversation (see plan()). */
68
+ plan?: PlanOptions;
69
+ /**
70
+ * RunOptions of the generated workflow's execution run, passed to
71
+ * engine.run verbatim (budgetUsd here is the EXECUTION ceiling,
72
+ * independent of the planning ceiling). Absent, the execution run is
73
+ * UNBOUNDED, as before.
74
+ */
75
+ run?: RunOptions;
52
76
  }
53
77
  interface PlanResult {
54
78
  source: string;
@@ -78,8 +102,11 @@ declare function plan(engine: Engine, goal: string, o?: PlanOptions): Promise<Pl
78
102
  /**
79
103
  * plan-then-run in one call (amended during M6-T05:
80
104
  * the composition is async because planning itself is a run).
105
+ * options.plan bounds the planning conversation, options.run bounds the
106
+ * generated workflow's execution; the two ceilings are independent, and
107
+ * the bare form without options runs BOTH legs unbounded, as before.
81
108
  */
82
- declare function runPlanned(engine: Engine, goal: string, args?: Json): Promise<RunHandle<unknown>>;
109
+ declare function runPlanned(engine: Engine, goal: string, args?: Json, options?: RunPlannedOptions): Promise<RunHandle<unknown>>;
83
110
  //#endregion
84
111
  //#region src/cassettes.d.ts
85
112
  /** The M3-convention cassette normalization: wall clock and spans only. */
package/dist/index.js CHANGED
@@ -188,7 +188,18 @@ async function plan(engine, goal, o) {
188
188
  repairRounds,
189
189
  ...o?.model === void 0 ? {} : { model: o.model }
190
190
  };
191
- const outcome = await engine.resume(planRunIdOf(goal), planWorkflow, { args }).result;
191
+ const runId = planRunIdOf(goal);
192
+ const recorded = (await engine.stores.journal.listRuns()).find((meta) => meta.runId === runId);
193
+ const existing = recorded !== void 0 || (await engine.stores.journal.load(runId)).length > 0;
194
+ const requested = o?.run?.budgetUsd;
195
+ if (existing && requested !== void 0 && recorded?.budgetUsd !== requested) process.emitWarning(`plan: run '${runId}' already has a planning journal ` + (recorded?.budgetUsd === void 0 ? "with no recorded budget ceiling" : `with its ceiling frozen at $${String(recorded.budgetUsd)}`) + `; the requested budgetUsd ${String(requested)} does not apply (delete the run or plan a new goal to change the ceiling)`, {
196
+ code: "RULVAR_PLAN_BUDGET_DRIFT",
197
+ type: "RulvarWarning"
198
+ });
199
+ const outcome = await (existing ? engine.resume(runId, planWorkflow, { args }) : engine.run(planWorkflow, args, {
200
+ runId,
201
+ ...o?.run
202
+ })).result;
192
203
  if (outcome.status !== "ok" || outcome.value === void 0) {
193
204
  const wire = outcome.error;
194
205
  throw new ScriptRejected(`plan: the planner run settled '${outcome.status}'${wire === void 0 ? "" : `: ${wire.message}`}`, { data: {
@@ -207,10 +218,13 @@ async function plan(engine, goal, o) {
207
218
  /**
208
219
  * plan-then-run in one call (amended during M6-T05:
209
220
  * the composition is async because planning itself is a run).
221
+ * options.plan bounds the planning conversation, options.run bounds the
222
+ * generated workflow's execution; the two ceilings are independent, and
223
+ * the bare form without options runs BOTH legs unbounded, as before.
210
224
  */
211
- async function runPlanned(engine, goal, args) {
212
- const planned = await plan(engine, goal);
213
- return engine.run(planned.workflow, args ?? null);
225
+ async function runPlanned(engine, goal, args, options) {
226
+ const planned = await plan(engine, goal, options?.plan);
227
+ return engine.run(planned.workflow, args ?? null, options?.run);
214
228
  }
215
229
  //#endregion
216
230
  //#region src/sandbox-runner.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/planner",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Rulvar flagship hybrid mode: plan agent, compileScript, WorkerSandboxRunner, self-repair loop.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -23,14 +23,14 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "eslint": "^9.39.4",
26
- "eslint-plugin-rulvar": "1.11.0",
27
- "@rulvar/core": "1.11.0"
26
+ "@rulvar/core": "1.12.0",
27
+ "eslint-plugin-rulvar": "1.12.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^22.20.0",
31
31
  "tsdown": "^0.22.3",
32
32
  "typescript": "~6.0.3",
33
- "@rulvar/testing": "1.11.0"
33
+ "@rulvar/testing": "1.12.0"
34
34
  },
35
35
  "repository": {
36
36
  "type": "git",