pi-onlyne 1.1.2 → 1.2.1

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.
@@ -128,22 +128,38 @@ test("heartbeat carries a full legal observation", () => {
128
128
  delivery: "none",
129
129
  resource: "attached",
130
130
  recovery: "none",
131
- outcome: "pending",
132
- public: "working",
133
131
  });
134
132
  });
135
133
 
136
134
  test("every observation is a state tuple the reducer calls legal", () => {
137
- // Mirrors onlyne-session's `project`: running works, idle/ready wait, booting creates.
138
- const expected = { booting: "created", ready: "idle", running: "working", idle: "idle", gone: "created" };
139
- for (const [agent, projected] of Object.entries(expected)) {
135
+ // The tuple carries no derived view and no task result any more: `Observation`
136
+ // dropped `public` and `outcome`, so the projection mapping that once had to be
137
+ // mirrored here is gone, and the key set is the whole contract.
138
+ const keys = [
139
+ "version",
140
+ "generation_live",
141
+ "isolate_after",
142
+ "terminate_after",
143
+ "mismatch_count",
144
+ "agent",
145
+ "delivery",
146
+ "resource",
147
+ "recovery",
148
+ ];
149
+ const agents = { booting: "booting", ready: "ready", running: "running", idle: "idle", gone: "booting" };
150
+ for (const [agent, state] of Object.entries(agents)) {
140
151
  const observed = observationFor(agent, { generation: 1, seq: 1 });
141
- assert.equal(observed.public, projected, `agent=${agent}`);
152
+ assert.deepEqual(Object.keys(observed), keys, `agent=${agent}`);
153
+ assert.equal(observed.agent, state, `agent=${agent}: gone travels as booting; only the host's grace declares death`);
142
154
  assert.notEqual(observed.isolate_after, 0);
143
155
  assert.notEqual(observed.terminate_after, 0);
144
- assert.equal(observed.outcome, "pending");
156
+ // The plugin can see neither the intent drain nor its own resource's close,
157
+ // and it does not pretend otherwise: the two placeholders below are
158
+ // overwritten by the client's composition, and `resource: attached` is the
159
+ // attach the host's dispatch path already recorded.
145
160
  assert.equal(observed.delivery, "none");
146
161
  assert.equal(observed.recovery, "none");
162
+ assert.equal(observed.resource, "attached");
147
163
  }
148
164
  });
149
165
 
@@ -238,7 +254,12 @@ test("the ledger head is capped at the plan's 200 characters", () => {
238
254
  test("an assignment becomes one message naming its origin and payload", { skip: !hasVectors }, () => {
239
255
  const assign = ASSIGN().args;
240
256
  const text = injectionText({ assign, proseIsNew: true });
241
- assert.match(text, /^\[onlyne\] task 11111111-1111-4111-8111-111111111111 from role:planner \(kind task\)/);
257
+ // The vector's causality names no hop budget, and the header is byte for byte
258
+ // the line this plugin has always injected.
259
+ assert.equal(
260
+ text.split("\n")[0],
261
+ "[onlyne] task 11111111-1111-4111-8111-111111111111 from role:planner (kind task)",
262
+ );
242
263
  assert.match(text, /\[onlyne\] role prose from the spec:\nRead the incoming task/);
243
264
  assert.match(text, /\nbuild it\n?$/);
244
265
 
@@ -247,6 +268,35 @@ test("an assignment becomes one message naming its origin and payload", { skip:
247
268
  assert.match(repeat, /build it/);
248
269
  });
249
270
 
271
+ test("the header names the hop and the budget once the family names a budget", () => {
272
+ const header = (causality) =>
273
+ injectionText({
274
+ assign: {
275
+ task_id: "t9",
276
+ envelope: {
277
+ id: "e9",
278
+ kind: "task",
279
+ from: { role: { role: "planner" } },
280
+ causality,
281
+ body: { text: "pass it on" },
282
+ },
283
+ },
284
+ proseIsNew: false,
285
+ }).split("\n")[0];
286
+
287
+ assert.equal(
288
+ header({ task: "t9", hop: 2, attempt: 0, family: "t1", hop_budget: 5 }),
289
+ "[onlyne] task t9 from role:planner (kind task, hop 2, hop budget 5)",
290
+ );
291
+ // A family may spend no further hop: zero is a figure the header carries.
292
+ assert.equal(
293
+ header({ task: "t9", hop: 0, attempt: 0, family: "t1", hop_budget: 0 }),
294
+ "[onlyne] task t9 from role:planner (kind task, hop 0, hop budget 0)",
295
+ );
296
+ // No budget named: the compat rule holds, hop or no hop.
297
+ assert.equal(header({ task: "t9", hop: 2, attempt: 0 }), "[onlyne] task t9 from role:planner (kind task)");
298
+ });
299
+
250
300
  test("an empty-bodied assignment still produces an instruction", () => {
251
301
  const text = injectionText({
252
302
  assign: { task_id: "t9", envelope: { id: "e9", kind: "note", from: { gateway: { gateway: "fg1", channel: "fake", conversation: "c1" } }, body: {} } },