@rulvar/plan 1.22.0 → 1.24.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.
Files changed (2) hide show
  1. package/dist/index.js +51 -2
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -2245,13 +2245,51 @@ function planRunner(options) {
2245
2245
  netLostUsd: view.netLostUsd
2246
2246
  };
2247
2247
  };
2248
+ /** True until boot completes: entries folded then are replays. */
2249
+ let absorbedAsReplay = true;
2250
+ const specAgentTypeOf = (nodeId) => (nodeId === void 0 ? void 0 : fold.specs[nodeId]?.agentType) ?? "unknown";
2251
+ /**
2252
+ * The one formatter for the spawn events of journal-embedded
2253
+ * admission rows (v1.22.0 review P2-5): PlanRunner journals every
2254
+ * admission INSIDE a carrying entry (a plan.revision, a ladder
2255
+ * verdict, an escalation decision), and before v1.23 none of them
2256
+ * emitted spawn:admitted / spawn:rejected at all. Recovered rows
2257
+ * emit with the standard replayed marker.
2258
+ */
2259
+ const emitSpawnDecisionRows = (entrySeq, rows, agentTypeAt, replayed) => {
2260
+ for (const [index, raw] of (rows ?? []).entries()) {
2261
+ const row = raw;
2262
+ const verdict = row.decision?.verdict;
2263
+ if (verdict?.kind === void 0) continue;
2264
+ const agentType = agentTypeAt(row, index);
2265
+ const options = replayed === true ? { replayed: true } : void 0;
2266
+ if (verdict.kind === "reject") io.emit({
2267
+ type: "spawn:rejected",
2268
+ entryRef: entrySeq,
2269
+ code: verdict.reason?.code ?? "unknown",
2270
+ agentType
2271
+ }, options);
2272
+ else if (verdict.kind === "admit" || verdict.kind === "reuse_full" || verdict.kind === "admit_graft") io.emit({
2273
+ type: "spawn:admitted",
2274
+ entryRef: entrySeq,
2275
+ verdict: verdict.kind,
2276
+ agentType,
2277
+ logicalTaskId: verdict.lineage?.logicalTaskId ?? "unknown",
2278
+ ...verdict.spawnUnitsAfter === void 0 ? {} : { spawnUnitsAfter: verdict.spawnUnitsAfter }
2279
+ }, options);
2280
+ }
2281
+ };
2248
2282
  const absorbPlan = () => {
2249
2283
  for (const entry of io.snapshot()) {
2250
2284
  if (entry.seq <= planCursor || entry.scope !== planScope) continue;
2251
2285
  if (entry.kind !== "plan.revision" && entry.kind !== "plan.decision") continue;
2252
2286
  fold = applyPlanEntry(fold, entry);
2253
2287
  planCursor = entry.seq;
2254
- if (entry.kind === "plan.revision") feedGuards(entry);
2288
+ if (entry.kind === "plan.revision") {
2289
+ feedGuards(entry);
2290
+ const value = entry.value;
2291
+ emitSpawnDecisionRows(entry.seq, value?.admissions, (row) => specAgentTypeOf(row.nodeId), absorbedAsReplay ? true : void 0);
2292
+ }
2255
2293
  }
2256
2294
  };
2257
2295
  /**
@@ -2536,12 +2574,13 @@ function planRunner(options) {
2536
2574
  attemptRef
2537
2575
  };
2538
2576
  const landVerdict = async (value) => {
2539
- await io.append({
2577
+ const verdictEntry = await io.append({
2540
2578
  scope: planScope,
2541
2579
  key: verdictKey,
2542
2580
  kind: "decision",
2543
2581
  value
2544
2582
  });
2583
+ emitSpawnDecisionRows(verdictEntry.seq, value.admissions, () => spec.agentType);
2545
2584
  if (value.raisesRung && value.nextAttempt !== void 0) {
2546
2585
  io.emit({
2547
2586
  type: "termination:debit",
@@ -2721,6 +2760,10 @@ function planRunner(options) {
2721
2760
  by: input.resolvedBy,
2722
2761
  countsAgainstLimit: value.countsAgainstLimit
2723
2762
  });
2763
+ const children = input.decision.kind === "decompose" ? input.decision.children : void 0;
2764
+ emitSpawnDecisionRows(entry.seq, input.admissions, (row, index) => {
2765
+ return children?.[index]?.agentType ?? specAgentTypeOf(row.nodeId ?? input.node.nodeId);
2766
+ });
2724
2767
  if (value.escalationUnitsAfter !== void 0) io.emit({
2725
2768
  type: "termination:debit",
2726
2769
  entryRef: entry.seq,
@@ -3624,6 +3667,12 @@ function planRunner(options) {
3624
3667
  absorbPlan();
3625
3668
  absorbLinks();
3626
3669
  await drainGuardVerdicts();
3670
+ for (const entry of io.snapshot()) {
3671
+ if (entry.kind !== "decision" || entry.scope !== planScope) continue;
3672
+ const value = entry.value;
3673
+ if (Array.isArray(value?.admissions)) emitSpawnDecisionRows(entry.seq, value.admissions, (row) => specAgentTypeOf(row.nodeId), true);
3674
+ }
3675
+ absorbedAsReplay = false;
3627
3676
  digests.set(0, {
3628
3677
  planHash: planHash(emptyPlan()),
3629
3678
  planSeq: -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/plan",
3
- "version": "1.22.0",
3
+ "version": "1.24.0",
4
4
  "description": "Rulvar adaptive orchestration extension: PlanRunner, RunLedger, escalation extensions, ModelLadder configuration.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,13 +22,13 @@
22
22
  "access": "public"
23
23
  },
24
24
  "dependencies": {
25
- "@rulvar/core": "1.22.0"
25
+ "@rulvar/core": "1.24.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.20.0",
29
29
  "tsdown": "^0.22.3",
30
30
  "typescript": "~6.0.3",
31
- "@rulvar/store-sqlite": "1.22.0"
31
+ "@rulvar/store-sqlite": "1.24.0"
32
32
  },
33
33
  "repository": {
34
34
  "type": "git",