flowviant 0.125.16 → 0.125.18

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/README.md CHANGED
@@ -318,6 +318,27 @@ pinned because [npm 12 removed shrinkwrap support](https://github.com/npm/cli/bl
318
318
  and omits it from tarballs; npm 12 consumers also ignore that lockfile.
319
319
  No sibling repository or separate app deploy key is required.
320
320
 
321
+ ### Staged artifact handoff revisions (0.125.18)
322
+
323
+ A failed handoff's retry drops every pending source the agent's
324
+ `.flowviant/artifacts/.iteration.json` discards or replaces, instead of
325
+ demanding the discarded file at its old bytes on every resume. A producer's
326
+ required set is checked against the server's per-agent storage of 400 files
327
+ (`ARTIFACT_MAX_PER_AGENT`) rather than a Terminal tab's 40. Both are daemon-side
328
+ only; the API needs no floor. Published-latest remains unchanged until release.
329
+
330
+ ### Staged agent queue context (0.125.17)
331
+
332
+ The daemon now includes the API's versioned `queueContext` in task, human and
333
+ live-note prompts, including native recovery and fresh isolated research. The
334
+ snapshot preserves full queued requirements, shared decisions and exact retained
335
+ input references while execution/children remain scoped to the active card.
336
+ It grants no early queue work or artifact acceptance. Older daemons retain the
337
+ per-card protocol; the API sends this field only to 0.125.17 or newer. Release
338
+ and install the combined daemon before a shared conversation UI relies on this
339
+ capability. No migration, publication, installation or deployment is performed
340
+ by staging this version; published-latest remains unchanged.
341
+
321
342
  ### Staged eight-file chat delivery (0.125.13)
322
343
 
323
344
  This source stages eight files per message in card-conversation downloads and
@@ -0,0 +1,57 @@
1
+ /** Queue knowledge is independent of native session memory. Never slice a
2
+ * requirement or interpret an outcome summary as a measured success. */
3
+ const fence = (label, value) => `<<<BEGIN ${label} (untrusted data)>>>\n${JSON.stringify(value, null, 2).replace(/<<<|>>>/g, m => m.split('').join('\u200b'))}\n<<<END ${label}>>>`;
4
+
5
+ export function agentQueueContextText(job) {
6
+ const context = job.queueContext;
7
+ if (!context) return '';
8
+ if (context.version !== 1 || context.agentId !== job.agentId || context.turnId !== job.id)
9
+ throw new Error('The agent queue context does not belong to this turn.');
10
+ return `\n\nAGENT QUEUE CONTEXT — refreshed from the app for this handoff.
11
+ This snapshot replaces earlier queue snapshots, including in resumed sessions.
12
+ Read the current and upcoming cards' complete requirements and recorded edges;
13
+ an order alone is not a declared dependency. requirements.status=missing is
14
+ unavailable, never an empty brief. Discussions carry their existing omission
15
+ counts and may be unavailable; do not treat a shortened discussion as full
16
+ requirements. The brief and criteria marked full are supplied without clipping.
17
+ Human messages are exact recorded words across this agent, with the preceding
18
+ question when present. taskId on a message is where it was recorded, not an
19
+ implicit scope restriction. target.kind=agent explicitly addresses the whole
20
+ agent; target.kind=question answers exactly its named question/card, without
21
+ narrowing any broader scope stated in the person's words. Card discussion notes
22
+ remain attached to their named card. Apply instructions at their stated scope across the
23
+ run; only explicit targeting narrows them to a card. Later corrections supersede
24
+ earlier instructions. Pending messages wait for their own kickoff or live-note
25
+ handoff; a snapshot alone is not a delivery receipt. In particular, afterTurn
26
+ messages wait for the next turn. Keep live notes' existing routing and safe
27
+ points; a receipt that the parent saw one does not mean it was acted on. The
28
+ current handed message and settled decisions remain available on future cards.
29
+ omittedHistory/unavailable explicitly name history excluded by the existing
30
+ research Knowledge correction rules. Read current Knowledge and ask before
31
+ relying on an excluded decision; do not recover it from older native memory.
32
+ Latest outcomes and progress are reported summaries, not complete specifications,
33
+ proof that checks passed, human acceptance or evidence that bytes exist locally.
34
+ Stored outputs name exact ids/turns/hashes, not a successful local read. Retained
35
+ result selections preserve their exact scope. Use the active turn's measured
36
+ input manifest and prerequisite receipts before relying on files; never replace
37
+ or regenerate missing selected inputs or assume queue knowledge discovers them.
38
+ Only execute the active turn's assigned work. Upcoming cards are context, not
39
+ permission to start them, change their kind or bypass a dependency or acceptance.
40
+ Keep this turn's product contract, write/research fence, chosen CLI/model,
41
+ delivery JSON and per-card commit attribution. Do not merge or accept for the
42
+ person. Pass children focused assignments, the active card's constraints and
43
+ only relevant prior findings/decisions/input identities, not the entire queue.
44
+ ${fence('AGENT QUEUE SNAPSHOT', context)}`;
45
+ }
46
+
47
+ /** The gate supplies active identity/fences, not upcoming work to a child.
48
+ * Relevant findings still travel with the root's focused assignment. */
49
+ export function agentChildScope(job) {
50
+ if (!job.queueContext) return '';
51
+ const card = job.queueContext.cards.find(c => c.taskId === (job.task?.id ?? job.queueContext.activeTaskId));
52
+ return `\n\nACTIVE CARD SCOPE. Work only on the orchestrator's focused assignment for this turn. Upcoming queued work is not authorized. Preserve this card's product kind, write/research fence, exact input identities and human acceptance rules. Ask the orchestrator for any missing relevant requirement, decision or prerequisite; do not infer success from a summary.\n${fence('CHILD ACTIVE CARD IDENTITY', {
53
+ agentId: job.agentId, turnId: job.id, taskId: card?.taskId ?? job.task?.id ?? null,
54
+ taskKind: job.taskKind ?? job.task?.taskKind ?? 'code', taskType: job.task?.taskType ?? null,
55
+ retainedResults: card?.retainedResults ?? [],
56
+ })}`;
57
+ }
@@ -23,6 +23,24 @@ const manifestText = (placeDir) => {
23
23
  const signature = (value) => value === null ? null : `${value.stamp}:${createHash('sha256').update(value.text).digest('hex')}`;
24
24
  export const iterationSignature = (placeDir) => signature(manifestText(placeDir));
25
25
 
26
+ /**
27
+ * Every name the standing declaration discards or replaces, whenever it was
28
+ * written. A failed handoff's retry reads this (2026-10-23): the agent revised
29
+ * its outputs in a turn that did not deliver, and the retry kept demanding the
30
+ * discarded files at their old bytes on every resume. Unreadable or malformed
31
+ * is no discard; the reporter refuses a malformed declaration on its own.
32
+ */
33
+ export function declaredDiscards(placeDir) {
34
+ const text = manifestText(placeDir);
35
+ if (text === null) return new Set();
36
+ try {
37
+ const value = JSON.parse(text.text);
38
+ const remove = Array.isArray(value?.remove) ? value.remove : [];
39
+ const replace = value?.replace && typeof value.replace === 'object' && !Array.isArray(value.replace) ? Object.keys(value.replace) : [];
40
+ return new Set([...remove, ...replace].filter(safeName));
41
+ } catch { return new Set(); }
42
+ }
43
+
26
44
  export function iterationChanges(placeDir, before) {
27
45
  const text = manifestText(placeDir);
28
46
  if (text === null || signature(text) === before?.iterationSignature) return { remove: [], replace: {} };
@@ -16,8 +16,10 @@ export const ARTIFACT_MAX_BYTES = 2097152;
16
16
  /** Binary model buffers (the extensions below). */
17
17
  export const ARTIFACT_BINARY_MODEL_MAX_BYTES = 20971520;
18
18
  export const ARTIFACT_BINARY_MODEL_EXTS = ['glb', 'bin', 'png', 'webp'];
19
- /** Per session and per agent — the server keeps as many per owner. */
19
+ /** Per Terminal session, and the per-turn discovery window. */
20
20
  export const ARTIFACT_MAX_PER_OWNER = 40;
21
+ /** Per agent — the server keeps as many for one agent. */
22
+ export const ARTIFACT_MAX_PER_AGENT = 400;
21
23
 
22
24
  /** Extension → the one mime the server serves it under; `text` is scrubbed. */
23
25
  export const ARTIFACT_TYPES = {
@@ -4,8 +4,9 @@
4
4
  import { createHash, randomUUID } from 'node:crypto';
5
5
  import { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync, readSync, renameSync, writeFileSync } from 'node:fs';
6
6
  import { basename, dirname, join } from 'node:path';
7
- import { ARTIFACT_MAX_DEPTH, artifactTypeFor, artifactMaxBytesFor, changedArtifacts, scanArtifacts } from './artifacts.mjs';
8
- import { ARTIFACT_BINARY_MODEL_MAX_BYTES, ARTIFACT_MAX_PER_OWNER } from './artifactPolicy.mjs';
7
+ import { ARTIFACT_MAX_DEPTH, artifactStoredName, artifactTypeFor, artifactMaxBytesFor, changedArtifacts, scanArtifacts } from './artifacts.mjs';
8
+ import { ARTIFACT_BINARY_MODEL_MAX_BYTES, ARTIFACT_MAX_PER_AGENT } from './artifactPolicy.mjs';
9
+ import { declaredDiscards } from './artifactIteration.mjs';
9
10
  import { ensureRealSubdir, realDirState } from './ownedDirs.mjs';
10
11
  import { scrub, secretIn } from './uplinkScrub.mjs';
11
12
  import { exportModelPage } from './modelExport.mjs';
@@ -147,9 +148,12 @@ export function createIntermediateArtifacts({ wt, agentId, path, exportPage = ex
147
148
  const changed = changedArtifacts(before, standing);
148
149
  // Failed export/storage retries are tied to a card and exact source hash.
149
150
  // A changed page is a new version; it never reuses a previous GLB receipt.
151
+ // A source the agent's iteration declaration discards or replaces is the
152
+ // explicit revision and leaves the retry set.
150
153
  const pending = state.pending?.taskId === taskId && taskId ? state.pending : null;
154
+ const discarded = pending ? declaredDiscards(wt) : new Set();
151
155
  if (pending) for (const ref of pending.sources) {
152
- if (changed.some(e => e.name === ref.name)) continue;
156
+ if (changed.some(e => e.name === ref.name) || discarded.has(artifactStoredName(ref.name))) continue;
153
157
  const entry = standing.find(e => e.name === ref.name);
154
158
  let bytes;
155
159
  try { bytes = readIntermediateFile(wt, `.flowviant/artifacts/${ref.name}`, artifactMaxBytesFor(ref.name)); }
@@ -192,11 +196,12 @@ export function createIntermediateArtifacts({ wt, agentId, path, exportPage = ex
192
196
  state.pending.sources = outputs.map(e => ({ name: e.name,
193
197
  sha256: hash(readIntermediateFile(wt, `.flowviant/artifacts/${e.name}`, artifactMaxBytesFor(e.name))) }));
194
198
  save(state);
195
- // The server retains 40 artifacts per owner. Discovery crowding is not a
196
- // storage limit, but uploading a larger required set would prune one of
197
- // this very handoff's files and then falsely claim complete delivery.
198
- if (outputs.length > ARTIFACT_MAX_PER_OWNER)
199
- throw new Error(`This producer requires ${outputs.length} output files including model exports; artifact storage retains at most ${ARTIFACT_MAX_PER_OWNER} files per agent. Narrow this producer's output set before retrying; its handoff is unfinished.`);
199
+ // The server retains ARTIFACT_MAX_PER_AGENT artifacts per agent. Discovery
200
+ // crowding is not a storage limit, but uploading a larger required set
201
+ // would prune one of this very handoff's files and then falsely claim
202
+ // complete delivery.
203
+ if (outputs.length > ARTIFACT_MAX_PER_AGENT)
204
+ throw new Error(`This producer requires ${outputs.length} output files including model exports; artifact storage retains at most ${ARTIFACT_MAX_PER_AGENT} files per agent. Narrow this producer's output set before retrying; its handoff is unfinished.`);
200
205
  const textures = [...state.files.flatMap(f => [...(/\.png$/i.test(f.name) ? [f] : []), ...(f.model?.textureInputs ?? [])]),
201
206
  ...outputs.filter(e => /\.png$/i.test(e.name)).map(e => snapshot(wt, e, identity, retain))]
202
207
  .map(({ name, path, sha256, taskId, turnId, agentId, taskKind }) => ({ name, path, sha256, taskId, turnId, agentId, taskKind }));
@@ -35,7 +35,7 @@ const text = (s, n) => scrubNativeText(s, n, scrub);
35
35
  * on Codex, only for a model in `catalog`, the measured spawnable models.
36
36
  */
37
37
  export async function createOrchestrator({ turnId, runtime, trace, admit, request = fleetRequest, notify = () => false, taken = () => {},
38
- interval = 500, hold = 60_000, clock = Date.now, scrubText = text, children = {}, readOnlyRun = null, signal, rootTools = null } = {}) {
38
+ interval = 500, hold = 60_000, clock = Date.now, scrubText = text, children = {}, readOnlyRun = null, signal, rootTools = null, assignmentContext = () => '' } = {}) {
39
39
  // Consults belong to a held attempt, never to a card turn. This capability
40
40
  // is entirely local; it cannot report routes or borrow an agent principal.
41
41
  if (readOnlyRun && (!['plan', 'capture'].includes(readOnlyRun.scope) || !filled(readOnlyRun.id) ||
@@ -159,7 +159,7 @@ export async function createOrchestrator({ turnId, runtime, trace, admit, reques
159
159
  ? `\n\nRead-only investigation agent record id: ${id}. FIRST call card_orchestrator.register_agent with agentId=${id} before work (tool discovery is allowed). Share this checkout and its repository/knowledge read boundary. Write no file, edit nothing, commit nothing, start no work and call no board or staging tool. Return findings, source paths and uncertainties in your final message to the coordinator. Ask questions only through card_orchestrator.agent_question with agentId=${id}, and read its answer before proceeding. ${readOnlyRun.scope === 'capture' ? 'Call no flowviant tool, including streaming. Only the coordinator dedupes and authors staged outcomes and asks the person through the existing single-question flowviant-ask fence.' : 'Only the coordinator reconciles the complete workload and returns the proposal.'}`
160
160
  : `\n\nCard orchestrator agent record id: ${id}. FIRST call card_orchestrator.register_agent with agentId=${id} before doing work (tool discovery is allowed). Share this worktree and preserve others’ edits. Ask questions through card_orchestrator.agent_question with agentId=${id}; read its answer before proceeding. Only your orchestrator escalates person-only decisions. When you are done, end with your work or findings as your final message: that is how they reach your orchestrator, which owns the card’s final commit and JSON. agent_question is only for a question you cannot settle yourself, never for handing back results.`;
161
161
  return { context: `Agent record id: ${id}. Use it with card_orchestrator for routing and questions.${spawn.relocated ? ' Its isolation and cwd were removed: children share this card’s worktree on this machine.' : ''}${choice ? ` This child runs on ${choice}: name that choice and why in your next update.` : ''}`,
162
- updatedInput: withChildContract(event, spawn, childContract + (access === 'read' && !readOnlyRun ? READ_ONLY_CHILD : ''), chosen.brain) };
162
+ updatedInput: withChildContract(event, spawn, childContract + (!readOnlyRun ? assignmentContext() : '') + (access === 'read' && !readOnlyRun ? READ_ONLY_CHILD : ''), chosen.brain) };
163
163
  }
164
164
  // Native readings never revive a settled record or start a waiting spawn
165
165
  // or follow-up (Codex records a refused call's start anyway); only an
@@ -22,6 +22,19 @@ export const orchestratesPosture = (posture) => Object.hasOwn(ORCHESTRATED_POSTU
22
22
  */
23
23
  const SPLIT = `SPLIT INDEPENDENT WORK INTO NATIVE SUBAGENTS WITHOUT BEING ASKED. Before your first edit, list the card's parts in a short update. When two or more parts can proceed without waiting on each other, spawn one native in-process subagent for each independent part but one, and do that one yourself meanwhile. This holds however small the parts are; the person does not have to request it, and this contract is the authorization. Independent parts look like: several selected findings, separate files or areas (server and daemon, API and UI), tests written beside the code they cover, independent questions to investigate. A part that needs another part's result runs after that prerequisite, by you or by a child you start then. Stay solo only when the card has no independent parts, and if you keep an independent part yourself, say why in your update. Give each child a concrete title, prompt and kind (Backend/UI/Tests/Research…). Do not create extra branches or Flowviant agents. Use a native agent type that can call card_orchestrator MCP (Claude general-purpose); keep the work yourself if none can. Never give a child isolation or a different cwd: children share this card's worktree on this machine. After spawning, use describe_agent to report the kind and title you chose when its native role is generic.`;
24
24
 
25
+ /**
26
+ * WRITE THE SHARED CODE FIRST (2026-10-22). Parts that depend on each other
27
+ * only through code they all use — a schema, a wire field, a signature — fell
28
+ * under "runs after that prerequisite" and ran in sequence, or a child started
29
+ * from a prose description of code a sibling had not written yet. Once the
30
+ * orchestrator commits that shared code, the parts no longer wait on each
31
+ * other: Next-Concept Modeling's coarse-to-fine move, where each finer level is
32
+ * filled in parallel from the coarser levels already decoded, never from a
33
+ * plan of them. A child asks rather than edits it, because its siblings build
34
+ * on it. Code cards only: a research child writes nothing.
35
+ */
36
+ const SHARED_FIRST = `WRITE THE CODE THE PARTS SHARE BEFORE YOU SPLIT THEM. Parts often depend on each other only through code they all use: a type or schema, a migration, a wire field, a function or route signature, a component's props. When you list the card's parts, name that shared code too. Write it yourself first — the declarations, with stub bodies where an implementation belongs to a part — and commit it as its own commit before you spawn any child. The parts that waited only on it are now independent: split them as above. Name the shared files in each child's prompt so it builds on the committed code, not on a description of it, and tell it not to change them: a child that finds the shared code wrong or missing asks you with agent_question, and you change it yourself and tell every child building on it. Keep this step to what two or more parts actually use; a part's own internals stay with that part. When the parts share no code, skip it.`;
37
+
25
38
  const RESEARCH = `THIS IS A RESEARCH CARD, SO EVERY CHILD ONLY READS. A child works inside this card's research fence: the same read fence, web policy and working directory as you. It writes no file, edits nothing and commits nothing, and the gate refuses a child's write. Give each child one question or one set of sources, and ask it to return its findings with their sources (links or repository paths) and what it could not verify. You alone deliver the card: merge the children's findings, resolve or state their conflicts, write any requested document yourself, and keep the research contract's own stops, including an investigation's numbered-findings question and its wait for the person's selection.`;
26
39
 
27
40
  /** Each CLI's own spelling of a child's model and effort, as measured
@@ -117,7 +130,8 @@ export function orchestratorContract({ posture = 'build', taskType = null, runti
117
130
  const reads = ORCHESTRATED_POSTURES[posture] === 'read';
118
131
  return `CARD ORCHESTRATOR — this applies to this card's one CLI and worktree.
119
132
  You are the model the person chose and remain responsible for the card and its final JSON.
120
- ${SPLIT}${taskType === 'tests' ? `\n${TESTS_SCOPE} Give every child this Tests scope explicitly.` : ''}${reads ? `\n${RESEARCH}` : ''}
133
+ When an agent queue snapshot is supplied, use it across resumed and fresh turns. Execute only the active card. A person's instruction keeps its stated scope across later cards; its recorded card is provenance, not an implicit target. Give each child a focused assignment with relevant prior findings, decisions and exact prerequisite references. Upcoming work never expands a child's assignment or the active card's product/write contract.
134
+ ${SPLIT}${reads ? '' : `\n${SHARED_FIRST}`}${taskType === 'tests' ? `\n${TESTS_SCOPE} Give every child this Tests scope explicitly.` : ''}${reads ? `\n${RESEARCH}` : ''}
121
135
  ${childBrain({ runtime, model, effort })}
122
136
 
123
137
  The daemon gates every native spawn against this project's Turns at once pool, shared with its other turns. Claude children run in the background so you remain available for messages and their questions; Codex spawns are already asynchronous. A refused spawn with a waiting id has not started. Keep working yourself; do not wait for it. When notified of a free slot, retry its native spawn (the same or a reworded prompt) or its native follow-up; the slot is held for about a minute, then offered again later. Never bypass this gate with another CLI process. The orchestrator itself also holds a slot. If no slot becomes available, finish the work yourself.
@@ -1,4 +1,5 @@
1
1
  import { imageRevisionInstructions } from './artifactIteration.mjs';
2
+ import { agentChildScope } from './agentQueueContext.mjs';
2
3
  import { measureTestFindings } from './testFindings.mjs';
3
4
  import { fetchResultInputs } from './resultInputs.mjs';
4
5
  import { agentWork } from './workActivity.mjs';
@@ -432,6 +433,7 @@ export function createAgentTurnExecution({
432
433
  try {
433
434
  if (orchestrating) {
434
435
  orchestrator = await createOrchestrator({ turnId, runtime: rt, trace, admit,
436
+ assignmentContext: () => agentChildScope(job),
435
437
  // Codex's spawn takes only a catalog model (knownCodexModels, the
436
438
  // measured models_cache.json rows the roster already reports).
437
439
  children: { access: ORCHESTRATED_POSTURES[posture], ...cardBrain, ...(rt === 'codex' ? { catalog: knownCodexModels() } : {}) },
@@ -447,9 +449,10 @@ export function createAgentTurnExecution({
447
449
  scope: 'agent', turnId, cwd: wt, sessionMetaPath, interrupted: () => run.interrupted,
448
450
  observe: message => orchestrator?.note(message),
449
451
  ...(rt === 'codex' ? { nativeIds: () => null } : {}),
450
- format: async (followup) => {
452
+ format: async (followup, { queueContext } = {}) => {
451
453
  orchestrator?.note(followup);
452
454
  const attached = followup.attachments?.length ? await fetchAgentFiles(wt, followup.attachments.map((file) => ({ ...file, from: 'message' }))) : { message: [], card: [] };
455
+ if (queueContext) job.queueContext = queueContext;
453
456
  return agentFollowupKickoff(job, followup, { messageFiles: attached.message, cardFiles: files.card, intermediateFiles, orchestrated: Boolean(orchestrator) });
454
457
  },
455
458
  })) } : {}),
@@ -26,6 +26,7 @@ import { AGENT_TASK_KICKOFF, AGENT_HUMAN_KICKOFF, SYSTEM_AGENT_FOR, withProjectC
26
26
  import { INTERNAL_WAIT_CONTRACT } from './agentInternalWait.mjs';
27
27
  import { orchestratorContract } from './orchestratorPrompt.mjs';
28
28
  import { intermediateArtifactContext } from './intermediateArtifacts.mjs';
29
+ import { agentQueueContextText } from './agentQueueContext.mjs';
29
30
 
30
31
  /** What every kickoff of this job is handed: the agent, the card and its
31
32
  * discussion, the job's context handoffs, the card's files, the place in
@@ -64,7 +65,7 @@ export const agentKickoff = (job, { cardFiles, messageFiles, intermediateFiles }
64
65
  // The files (0.112.0): the person's inside their words, the
65
66
  // card's at the foot of its discussion.
66
67
  messageFiles,
67
- })) + intermediateArtifactContext(intermediateFiles);
68
+ })) + agentQueueContextText(job) + intermediateArtifactContext(intermediateFiles);
68
69
 
69
70
  /** A live message sent while the turn runs, as the CLI is handed it — on an
70
71
  * orchestrated card with its id, so the route it takes is reported. */
@@ -74,7 +75,7 @@ export const agentFollowupKickoff = (job, followup, { cardFiles, messageFiles, i
74
75
  message: followup.body + (followup.libraryPrompt ?? '') + (orchestrated ? `\nMessage id: ${followup.id}. Choose and report its route with card_orchestrator.route_message.` : ''),
75
76
  askedByName: followup.askedByName,
76
77
  messageFiles,
77
- }) + intermediateArtifactContext(intermediateFiles);
78
+ }) + agentQueueContextText(job) + intermediateArtifactContext(intermediateFiles);
78
79
 
79
80
  /** The turn's system prompt, in its fixed section order. `orchestration` is
80
81
  * null on a solo run, else what the contract names: `{ posture, runtime,
@@ -77,7 +77,7 @@ export function createLiveMessages({ scope, turnId, attempt, cwd, sessionMetaPat
77
77
  if (stopped || interrupted()) break;
78
78
  if (taken.has(message.id) || seen?.has(message.id)) { onTaken(message.id); continue; }
79
79
  if (sent.has(message.id)) continue;
80
- const prompt = await format(message);
80
+ const prompt = await format(message, { queueContext: result.json.data.queueContext });
81
81
  if (!stopped && !interrupted() && send(message.id, prompt)) sent.add(message.id);
82
82
  }
83
83
  })().catch(() => {}).finally(() => { flight = null; });
@@ -106,7 +106,7 @@ export function createLiveMessages({ scope, turnId, attempt, cwd, sessionMetaPat
106
106
  onTaken(turnId); // the native transcript proves the original prompt was read
107
107
  initialId = randomUUID(); // continuation, never a second copy of the user's UUID
108
108
  initialIds.add(initialId);
109
- return 'Continue the request already in this conversation after the process stopped. Inspect the work in flight before repeating a command, and finish under the same operating contract.';
109
+ return 'Continue the request already in this conversation after the process stopped. Inspect the work in flight before repeating a command, and finish under the same operating contract.' + (scope === 'agent' ? `\n\nCurrent handoff (refresh its queue/context and retain the active card contract; do not repeat completed actions):\n${prompt}` : '');
110
110
  }
111
111
  return prompt;
112
112
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowviant",
3
- "version": "0.125.16",
3
+ "version": "0.125.18",
4
4
  "description": "Run your own coding CLIs as build agents for Flowviant \u2014 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": {