flowviant 0.104.0 → 0.106.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.
@@ -187,8 +187,8 @@ export function createAgentTurnExecution({
187
187
  * owner's loop ("iterate in the review column, the agent opened") that
188
188
  * could edit code on an ask that was a mockup. So the server projects the
189
189
  * kind of the card the turn is ABOUT onto the job itself (`taskKind`,
190
- * sent only for design and research; the same `DAEMON_TASK_KIND_MIN`
191
- * floor as the card's own key, no new one), and the card's key stays the
190
+ * sent for every non-code kind; the card's own key's floor, no new one),
191
+ * and the card's key stays the
192
192
  * fallback for a server that sends only that. Absent on both is code.
193
193
  */
194
194
  /**
@@ -282,7 +282,9 @@ export function createAgentTurnExecution({
282
282
  * what was asked for either way.
283
283
  *
284
284
  * ONE SPEC BUILDER (`AGENT_TASK_SPEC`) shared with the kickoff below, so
285
- * what the reviewer reads is byte-identical to what the agent read.
285
+ * what the reviewer reads is byte-identical to what the agent read — the
286
+ * card's discussion included (0.106.0): both are handed the same
287
+ * `job.cardThread`, and the builder prints it inside the spec.
286
288
  * Failure is swallowed inside `stashCard`: a note about a turn may never
287
289
  * cost the turn.
288
290
  */
@@ -290,7 +292,7 @@ export function createAgentTurnExecution({
290
292
  stashCard(
291
293
  sessionMetaPath(wt, 'flowviant-agent-cards', agentId),
292
294
  job.task.id,
293
- AGENT_TASK_SPEC(job.task)
295
+ AGENT_TASK_SPEC(job.task, job.cardThread)
294
296
  );
295
297
  }
296
298
 
@@ -372,6 +374,9 @@ export function createAgentTurnExecution({
372
374
  ? AGENT_TASK_KICKOFF({
373
375
  agentName: job.agentName,
374
376
  task: job.task,
377
+ // The card's discussion (0.106.0), printed inside THE CARD by
378
+ // the same builder the stash above wrote down.
379
+ cardThread: job.cardThread,
375
380
  position: job.position ?? 1,
376
381
  total: job.total ?? 1,
377
382
  })
@@ -380,6 +385,9 @@ export function createAgentTurnExecution({
380
385
  message: job.body ?? '',
381
386
  askedByName: job.askedByName,
382
387
  task: job.task,
388
+ // The discussion on the one card this message is about, in a
389
+ // fence of its own after the person's words (0.106.0).
390
+ cardThread: job.cardThread,
383
391
  position: job.position ?? 1,
384
392
  total: job.total ?? 1,
385
393
  }),
@@ -72,12 +72,15 @@ export function agentTurnSettlement({ turnId, job, kind, out, lastAnswer, usage,
72
72
  });
73
73
  }
74
74
  /**
75
- * A DESIGN OR RESEARCH CARD IS NOT DELIVERED UNTIL ITS ARTIFACT EXISTS
76
- * (0.97.0) — measured, never taken on the agent's word.
75
+ * A NON-CODE CARD IS NOT DELIVERED UNTIL ITS ARTIFACT EXISTS (0.97.0;
76
+ * the 3D-model and presentation kinds 0.105.0) — measured, never taken on
77
+ * the agent's word.
77
78
  *
78
- * Its whole product is one file under `.flowviant/artifacts/`: a `.html`
79
- * mockup for design, a `.md` write-up for research. A turn that says
80
- * "delivered" without having written one would land the agent in Review
79
+ * Its product is under `.flowviant/artifacts/`, and the kind's table
80
+ * (agentTaskKinds.mjs) says which file proves it: a `.html` mockup for
81
+ * design, a `.html` deck, a `.md` write-up for research, and for a 3D
82
+ * model a `.html` viewer AND a `.gltf`/`.glb`/`.obj` beside it. A turn that
83
+ * says "delivered" without having written one would land the agent in Review
81
84
  * with nothing to look at and a summary describing a page that does not
82
85
  * exist — so it settles `nothing` with the measured sentence, and the
83
86
  * agent lands in Stuck with a true reason instead.
@@ -105,10 +108,19 @@ export function agentTurnSettlement({ turnId, job, kind, out, lastAnswer, usage,
105
108
  */
106
109
  if (res.outcome === 'delivered' && kind.artifact) {
107
110
  const want = kind.artifact.match;
111
+ // THE 3D-MODEL KIND'S SECOND PROOF (0.105.0): its viewer page alone is a
112
+ // page, not a model — a `.gltf`/`.glb`/`.obj` must stand beside it. A
113
+ // task turn delivers when it wrote EITHER half this turn and BOTH stand
114
+ // (a re-modelled mesh — a rewritten .gltf/.glb/.obj — need not rewrite
115
+ // its viewer; a texture or .mtl alone is neither half). The halves are
116
+ // not paired by folder (pinned in the test). With no companion this is
117
+ // exactly the one-file rule design, deck and research have.
118
+ const also = kind.artifact.companion;
119
+ const need = (l) => l.some((e) => want.test(e.name)) && (!also || l.some((e) => also.test(e.name)));
108
120
  const standing = scanArtifacts(wt);
109
- const wrote = changedArtifacts(artifactsBefore, standing).some((e) => want.test(e.name));
110
- const present =
111
- wrote || ((job.kind !== 'task' || job.redo === true) && standing.some((e) => want.test(e.name)));
121
+ const touched = changedArtifacts(artifactsBefore, standing);
122
+ const wrote = touched.some((e) => want.test(e.name) || also?.test(e.name)) && need(standing);
123
+ const present = wrote || ((job.kind !== 'task' || job.redo === true) && need(standing));
112
124
  if (!present) {
113
125
  return report({
114
126
  turnId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowviant",
3
- "version": "0.104.0",
3
+ "version": "0.106.0",
4
4
  "description": "Run your own coding CLIs as build agents for Flowviant — Claude Code, Codex or Antigravity, on your own credentials. Holds your sessions, keeps a worktree per tab, and ships branches on your word.",
5
5
  "type": "module",
6
6
  "bin": {