flowviant 0.125.5 → 0.125.7

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 (101) hide show
  1. package/README.md +4 -5
  2. package/bin/lib/agentInternalWait.mjs +1 -5
  3. package/bin/lib/agentPlan.mjs +13 -163
  4. package/bin/lib/agentRepositories.mjs +3 -1
  5. package/bin/lib/claudeInput.mjs +89 -10
  6. package/bin/lib/claudeMachineMcp.mjs +85 -0
  7. package/bin/lib/claudePersonal.mjs +6 -57
  8. package/bin/lib/claudePosture.mjs +6 -15
  9. package/bin/lib/claudeSettingsArg.mjs +67 -0
  10. package/bin/lib/claudeStream.mjs +30 -1
  11. package/bin/lib/claudeSubagentProgress.mjs +12 -28
  12. package/bin/lib/claudeSubagents.mjs +4 -2
  13. package/bin/lib/codexContract.mjs +52 -0
  14. package/bin/lib/codexFencedMount.mjs +275 -0
  15. package/bin/lib/codexPersonal.mjs +1 -265
  16. package/bin/lib/codexProjectRead.mjs +5 -4
  17. package/bin/lib/codexResearch.mjs +9 -3
  18. package/bin/lib/codexSubagentEvents.mjs +11 -7
  19. package/bin/lib/codexSubagents.mjs +55 -52
  20. package/bin/lib/codexToml.mjs +328 -0
  21. package/bin/lib/config.mjs +22 -1
  22. package/bin/lib/conversationIds.mjs +10 -0
  23. package/bin/lib/fleet.mjs +2 -2
  24. package/bin/lib/git.mjs +32 -0
  25. package/bin/lib/heldTool.mjs +49 -0
  26. package/bin/lib/hooks/mcpAllow.mjs +11 -5
  27. package/bin/lib/hooks/orchestrator.mjs +20 -10
  28. package/bin/lib/intakeDraft.mjs +1 -1
  29. package/bin/lib/jsonlTail.mjs +52 -0
  30. package/bin/lib/mcpInventory.mjs +11 -6
  31. package/bin/lib/mcpReasons.mjs +26 -0
  32. package/bin/lib/mcpReportBounds.mjs +10 -0
  33. package/bin/lib/mcpStdio.mjs +35 -0
  34. package/bin/lib/mergeBatch.mjs +6 -24
  35. package/bin/lib/mergeOrder.mjs +18 -0
  36. package/bin/lib/modelJson.mjs +173 -0
  37. package/bin/lib/nativeAgentTools.mjs +72 -0
  38. package/bin/lib/orchestrator.mjs +221 -133
  39. package/bin/lib/orchestratorClient.mjs +17 -21
  40. package/bin/lib/orchestratorHooks.mjs +21 -4
  41. package/bin/lib/orchestratorNative.mjs +58 -0
  42. package/bin/lib/orchestratorPrompt.mjs +7 -4
  43. package/bin/lib/orchestratorProtocol.mjs +25 -3
  44. package/bin/lib/postureTools.mjs +58 -13
  45. package/bin/lib/prWorkflow.mjs +13 -2
  46. package/bin/lib/processGroup.mjs +41 -0
  47. package/bin/lib/projectRepositories.mjs +2 -2
  48. package/bin/lib/projectToolRuntimes.mjs +92 -245
  49. package/bin/lib/projectTools.mjs +60 -19
  50. package/bin/lib/prompts.mjs +47 -18
  51. package/bin/lib/reportJournal.mjs +61 -0
  52. package/bin/lib/repositoryDelivery.mjs +6 -4
  53. package/bin/lib/repositoryMerge.mjs +8 -12
  54. package/bin/lib/repositoryPlaces.mjs +2 -2
  55. package/bin/lib/repositoryPrompts.mjs +42 -0
  56. package/bin/lib/repositoryTool.mjs +9 -32
  57. package/bin/lib/researchUse.mjs +39 -0
  58. package/bin/lib/resumeLost.mjs +21 -1
  59. package/bin/lib/resumeMarker.mjs +43 -0
  60. package/bin/lib/runTurn.mjs +55 -52
  61. package/bin/lib/runtimeAntigravity.mjs +1 -1
  62. package/bin/lib/runtimeCapabilities.mjs +13 -18
  63. package/bin/lib/runtimeClaude.mjs +68 -24
  64. package/bin/lib/runtimeCodex.mjs +12 -6
  65. package/bin/lib/runtimeEvents.mjs +13 -2
  66. package/bin/lib/runtimeOfferings.mjs +12 -5
  67. package/bin/lib/runtimes.mjs +3 -1
  68. package/bin/lib/startProject.mjs +10 -0
  69. package/bin/lib/subagentBounds.mjs +20 -0
  70. package/bin/lib/trace.mjs +30 -5
  71. package/bin/lib/turnDeclaration.mjs +1 -1
  72. package/bin/lib/turnDiagnostics.mjs +9 -12
  73. package/bin/lib/turnReceipts.mjs +64 -0
  74. package/bin/lib/turnSubagents.mjs +91 -0
  75. package/bin/lib/turnUsage.mjs +9 -6
  76. package/bin/lib/update.mjs +18 -4
  77. package/bin/lib/versionOrder.mjs +11 -1
  78. package/bin/lib/work.mjs +9 -9
  79. package/bin/lib/workAgentMerges.mjs +5 -7
  80. package/bin/lib/workAgentPrecheck.mjs +5 -5
  81. package/bin/lib/workAgentRecovery.mjs +2 -1
  82. package/bin/lib/workAgentResume.mjs +121 -0
  83. package/bin/lib/workAgentTools.mjs +111 -0
  84. package/bin/lib/workAgentTurnExecution.mjs +82 -246
  85. package/bin/lib/workAgentTurnOutcome.mjs +30 -3
  86. package/bin/lib/workAgentTurnReports.mjs +16 -0
  87. package/bin/lib/workAgentTurnShape.mjs +90 -0
  88. package/bin/lib/workAgentTurns.mjs +28 -12
  89. package/bin/lib/workArtifactReconcile.mjs +3 -2
  90. package/bin/lib/workAttachments.mjs +27 -5
  91. package/bin/lib/workMergeBatch.mjs +7 -5
  92. package/bin/lib/workNarration.mjs +32 -0
  93. package/bin/lib/workPlaceReports.mjs +3 -3
  94. package/bin/lib/workPlaces.mjs +14 -0
  95. package/bin/lib/workReportQueue.mjs +18 -1
  96. package/bin/lib/workSessionRuntime.mjs +2 -5
  97. package/bin/lib/workSessionTurns.mjs +68 -80
  98. package/bin/lib/workShip.mjs +8 -18
  99. package/bin/lib/workTurnShape.mjs +6 -4
  100. package/bin/lib/worktreeDiff.mjs +29 -5
  101. package/package.json +1 -1
@@ -0,0 +1,121 @@
1
+ /**
2
+ * AN AGENT'S RESUME ACROSS TURNS — which conversation its next turn speaks
3
+ * in, and the kept Codex home that conversation is filed under (2026-10-18,
4
+ * the SOLID pass).
5
+ *
6
+ * The seam ARCHITECTURE named for workAgentTurnExecution.mjs ("the
7
+ * resume-marker read and write is its seam"), taken. Resume mechanics have
8
+ * changed four times — the Codex thread pin (2026-09-24), the ran marker only
9
+ * a Claude turn writes (2026-09-24), the kept Codex home (2026-09-29), the
10
+ * per-agent Claude session marker (2026-10-14) — and each time across six
11
+ * separated sites of the run: the reads and the resume decision, the home,
12
+ * the session pinned at init, the thread seen mid-turn, the fresh retry's
13
+ * reset, and the writes after the turn. They sit together here, the per-CLI
14
+ * arms moved verbatim, so neither the decision nor the write order can shift;
15
+ * giving another CLI an agent resume by id is an edit to this file. The read
16
+ * and write procedure is resumeMarker.mjs's, and the id shapes and the
17
+ * Claude marker name are conversationIds.mjs's; the agent's own marker names
18
+ * are spelled here alone.
19
+ *
20
+ * THE RUN KEEPS THE ORDERING: it calls `agentTurnResume` where the reads
21
+ * stood, before the turn's files are fetched, and `persist()` where the
22
+ * writes stood — after the CLI's children are dropped and the trace tail is
23
+ * flushed, before the worktree is re-measured.
24
+ */
25
+ import { existsSync, writeFileSync } from 'node:fs';
26
+ import { CLAUDE_SESSION_RE, CODEX_THREAD_RE, RESUME_MARKERS } from './conversationIds.mjs';
27
+ import { pinId, readPinnedId } from './resumeMarker.mjs';
28
+
29
+ /**
30
+ * One agent turn's resume. `sessionMetaPath` is the lane's (a path in the
31
+ * worktree's private git dir, or null). Returns the turn's `resume` and
32
+ * `resumeThreadId`, the kept `codexHome`, and what the run tells it as the
33
+ * CLI speaks: `sawSession` (Claude's init), `sawThread` (Codex's
34
+ * `thread.started`), `forgetThread` (a lost resume retried fresh), `threadNow`
35
+ * and, once the turn is over, `persist`.
36
+ */
37
+ export function agentTurnResume({ rt, wt, agentId, sessionMetaPath }) {
38
+ // ONE AGENT IS ONE DIRECTORY, so the CLI's own cwd-keyed resume is exactly
39
+ // right here — the ambiguity that forced per-tab session pinning in the
40
+ // Workbench (many tabs, one place) cannot arise. The marker is what
41
+ // distinguishes the first turn from every later one across restarts.
42
+ //
43
+ // IT MEANS "CLAUDE HAS SPOKEN HERE", and since 2026-09-24 only a Claude
44
+ // turn writes it: an agent can be switched between CLIs, and a marker a
45
+ // codex turn left behind would send the first Claude turn to
46
+ // `--continue` a directory holding no Claude conversation at all.
47
+ const ranMarker = sessionMetaPath(wt, 'flowviant-agent-ran');
48
+ /**
49
+ * CODEX RESUMES BY ITS OWN THREAD ID, PINNED PER AGENT (2026-09-24).
50
+ *
51
+ * Resume was Claude-only, because codex's `resume --last` is
52
+ * MACHINE-GLOBAL and would cross-resume whichever conversation spoke
53
+ * last anywhere on the box. The cost was that every codex card started
54
+ * a stranger: no memory of the card before it, and — worse — an answer
55
+ * to the agent's own question arrived at a codex that never asked it.
56
+ * The Workbench solved the same problem in 0.69.0 by pinning the id
57
+ * `thread.started` announces; this is that, keyed by the AGENT rather
58
+ * than a tab. The id is shape-checked before it rides argv.
59
+ */
60
+ const codexThreadMarker =
61
+ rt === 'codex' ? sessionMetaPath(wt, 'flowviant-agent-codex-thread', agentId) : null;
62
+ // An unreadable or misshapen marker is unknown: run fresh (resumeMarker.mjs).
63
+ const codexResumeId = readPinnedId(codexThreadMarker, CODEX_THREAD_RE);
64
+ let seenThreadId = null;
65
+ const claudeMarker = rt === 'claude' ? sessionMetaPath(wt, RESUME_MARKERS.claude, agentId) : null;
66
+ const claudeResumeId = readPinnedId(claudeMarker, CLAUDE_SESSION_RE);
67
+ const resume =
68
+ rt === 'codex'
69
+ ? Boolean(codexResumeId)
70
+ : rt === 'claude' && (Boolean(claudeResumeId) || Boolean(ranMarker && existsSync(ranMarker)));
71
+ /**
72
+ * …AND THE HOME THAT THREAD IS FILED UNDER, KEPT PER AGENT (2026-09-29).
73
+ *
74
+ * Codex's thread index records each rollout under the CODEX_HOME the turn
75
+ * ran with, as that path — not the personal store the link leads to — so
76
+ * the per-turn home in /tmp every turn used to get died with its turn and
77
+ * took the pinned thread with it: the next card's `resume` failed "no
78
+ * rollout found" and the agent went to Stuck. Beside the thread marker,
79
+ * in the worktree's private git dir: outside the working tree (never
80
+ * committed, never seen by `git add -A`), refreshed by every turn and
81
+ * removed only with the worktree, when the agent retires and its threads
82
+ * stop mattering. One agent runs one turn at a time (its place's writer
83
+ * lock), so no two turns refresh it at once. Null (no git dir to hold it)
84
+ * is the per-turn home again, and a lost resume then runs once fresh.
85
+ */
86
+ const codexAgentHome =
87
+ rt === 'codex' ? sessionMetaPath(wt, 'flowviant-agent-codex-home', agentId) : null;
88
+
89
+ return {
90
+ resume,
91
+ resumeThreadId: codexResumeId || claudeResumeId || undefined,
92
+ codexHome: codexAgentHome,
93
+ /** Claude's session id from its init, pinned at once (a Claude turn only). */
94
+ sawSession(id) {
95
+ pinId(claudeMarker, CLAUDE_SESSION_RE, id);
96
+ },
97
+ /** The thread Codex announced; a blank one keeps the last. */
98
+ sawThread(id) {
99
+ seenThreadId = String(id ?? '').trim() || seenThreadId;
100
+ },
101
+ /** A lost resume runs fresh: the thread it had seen is not its own. */
102
+ forgetThread() {
103
+ seenThreadId = null;
104
+ },
105
+ threadNow: () => seenThreadId,
106
+ persist() {
107
+ if (ranMarker && rt === 'claude') {
108
+ try {
109
+ writeFileSync(ranMarker, '1');
110
+ } catch {
111
+ /* a missing marker only costs one un-resumed turn */
112
+ }
113
+ }
114
+ // The thread THIS turn spoke under, pinned so the next card, answer
115
+ // or merge-resolve resumes it. After the turn, like the tab lane: an
116
+ // id learned mid-turn is only true once the turn that learned it ends.
117
+ // Best-effort — the next turn runs fresh.
118
+ pinId(codexThreadMarker, CODEX_THREAD_RE, seenThreadId);
119
+ },
120
+ };
121
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * WHAT A CARD TURN MOUNTS, AND WHAT IT IS TOLD (2026-10-18, the SOLID pass).
3
+ *
4
+ * Split out of workAgentTurnExecution.mjs, where it had become a second
5
+ * vocabulary inside one agent turn's run: the base-branch snapshot read across
6
+ * the card's repository sources, the daemon's own turn servers, Claude's
7
+ * machine servers beside the base copy or Codex's fenced mount, and the TOOLS
8
+ * note that says all of it to the agent. Those change together — three
9
+ * 2026-10-17 commits (703750746, 2cc52e42c, 65051ac42) edited this block and
10
+ * nothing else of the run — and for reasons the run does not share. Whether a
11
+ * CLI takes MCP at all is asked of the tool table (`runnerToolCapabilities`,
12
+ * projectToolRuntimes.mjs) rather than listed again here, and the daemon's
13
+ * server names are spelled once (`CARD_TURN_SERVERS`), so a base `.mcp.json`
14
+ * that reuses one is still never told to the agent as a project server.
15
+ *
16
+ * THE RUN KEEPS THE ORDERING: it calls this after `createOrchestrator` (whose
17
+ * config is one of the turn servers), inside the try whose finally cleans the
18
+ * prepared tools up, and merges the returned `env` into the CLI's `mcpEnv`
19
+ * ahead of the repository tool's and the orchestrator's. Until this returns
20
+ * the run holds no handle to clean, so a throw after the tools are prepared
21
+ * cleans them up here.
22
+ */
23
+ import { mcpJsonServerNamesAbove, readBaseTools, prepareAgentTools } from './projectTools.mjs';
24
+ import { runnerToolCapabilities } from './projectToolRuntimes.mjs';
25
+ import { TURN_PROFILES } from './turnProfile.mjs';
26
+ import { postureToolsNote } from './postureTools.mjs';
27
+ import { machineMcpServers } from './claudeMachineMcp.mjs';
28
+ import { ORCHESTRATOR_SERVER } from './orchestratorProtocol.mjs';
29
+
30
+ /** The servers the daemon itself mounts on a card turn, by the names the
31
+ * agent calls them: a multi-repository card's add_repository, and an
32
+ * orchestrated card's routing. Never a project server's, whatever the base
33
+ * `.mcp.json` names. */
34
+ export const CARD_TURN_SERVERS = Object.freeze({ repositories: 'card_repositories', orchestrator: ORCHESTRATOR_SERVER });
35
+
36
+ /**
37
+ * The card turn's tools, prepared, and what it is told of them.
38
+ *
39
+ * `baseRef` is the lane's own function, read only when the card's worktree is
40
+ * none of its repository sources. `env` is the environment the turn expands
41
+ * from and `machineServers` claudeMachineMcp.mjs's reader: the process's own in
42
+ * the lane, a scratch home in a test. Returns `{ projectTools, toolsNote, env,
43
+ * envNeeded, mountArgs }` — the prepared tools (the caller cleans them up
44
+ * from here), the note, the mount's part of the CLI's `mcpEnv` and whether it
45
+ * needs one, and the keys the runner takes the mount as.
46
+ */
47
+ export function prepareCardTools({ rt, posture, wt, repoRoot, baseRef, sources = [], repositoryTool = null, orchestratorConfig = null, orchestrated = false, codexHome = null, env = process.env, machineServers = machineMcpServers }) {
48
+ // A turn reads the base ref afresh. Changes the agent has made to its
49
+ // own worktree cannot silently change the next turn's tools.
50
+ const source = sources.find((r) => r.wt === wt);
51
+ const snapshot = readBaseTools(source?.repoRoot ?? repoRoot, source?.baseRef ?? baseRef());
52
+ for (const other of sources.filter((r) => r !== source)) {
53
+ const base = readBaseTools(other.repoRoot, other.baseRef);
54
+ snapshot.instructions.push(...[...base.instructions, ...base.skillFiles].map((file) => ({ ...file, path: `repositories/${other.folder}/${file.path}` })));
55
+ }
56
+ const projectTools = prepareAgentTools(snapshot, rt, env, wt, { codexHome, fenced: posture !== 'build', turnServers: {
57
+ ...(repositoryTool ? { [CARD_TURN_SERVERS.repositories]: repositoryTool.config } : {}),
58
+ ...(orchestratorConfig ? { [CARD_TURN_SERVERS.orchestrator]: orchestratorConfig } : {}),
59
+ } });
60
+ try {
61
+ const mountsProjectMcp = TURN_PROFILES[posture]?.projectMcp === true && runnerToolCapabilities(rt).mcp;
62
+ // A fenced posture on a runner that ignores its own file there (Codex's
63
+ // `--ignore-user-config`) takes the servers as `fencedMount` instead.
64
+ const fencedMount = mountsProjectMcp && posture !== 'build' ? projectTools.fencedMount : null;
65
+ // THE MACHINE'S OWN SERVERS ON CLAUDE (2026-10-11, the owner): the turn
66
+ // is not strict, and every `.mcp.json` name from the worktree up is
67
+ // disabled so only the base copy speaks for the project. Null (an
68
+ // unboundable walk) mounts strictly: the base copy alone.
69
+ const claudeDisabled = mountsProjectMcp && rt === 'claude' ? mcpJsonServerNamesAbove(wt) : null;
70
+ // The machine's servers by name, as its CLI's own config lists them
71
+ // (2026-10-17): a card that is told only "the machine's servers" and
72
+ // finds none in a deferred tool list concludes it has no MCP at all.
73
+ // A Codex code card's are the ones its kept config.toml mounts
74
+ // (2026-10-18), never the fenced mount's narrower list.
75
+ const baseNames = projectTools.mcpServers.filter((name) => !Object.values(CARD_TURN_SERVERS).includes(name));
76
+ const claudeMachine = claudeDisabled != null ? machineServers({ user: true, checkout: source?.repoRoot ?? repoRoot, env }) : {};
77
+ const machineNames = !mountsProjectMcp ? [] : rt === 'claude'
78
+ ? (claudeMachine == null ? null : Object.keys(claudeMachine).filter((name) => !projectTools.mcpServers.includes(name)))
79
+ : posture !== 'build' ? (projectTools.fencedMount ? projectTools.fencedMount.machine : []) : projectTools.codexMachineServers;
80
+ // What this card's posture withholds, said to the agent — with the
81
+ // servers it did and did not mount, and why — so it relays the fence
82
+ // instead of inventing a setting (postureTools.mjs). Empty for a code card.
83
+ const toolsNote = postureToolsNote({
84
+ posture,
85
+ runtime: rt,
86
+ orchestrated,
87
+ mounted: !mountsProjectMcp ? [] : fencedMount ? fencedMount.mounted : baseNames,
88
+ machine: mountsProjectMcp && (rt === 'codex' || claudeDisabled != null),
89
+ machineNames,
90
+ unmounted: [...projectTools.mcpUnmounted.map((u) => ({ ...u, source: 'project' })), ...(fencedMount ? fencedMount.unmounted : [])],
91
+ });
92
+ return {
93
+ projectTools,
94
+ toolsNote,
95
+ env: { ...(projectTools.codexHome ? { CODEX_HOME: projectTools.codexHome } : {}), ...(fencedMount?.env ?? {}) },
96
+ envNeeded: Boolean(projectTools.codexHome || fencedMount),
97
+ // Reviewed project servers and the machine's configured servers, on
98
+ // initial cards, answers and review iterations alike.
99
+ mountArgs: mountsProjectMcp && rt === 'claude'
100
+ ? {
101
+ mcpArgs: [...(claudeDisabled ? [] : ['--strict-mcp-config']), '--mcp-config', projectTools.mcpPath],
102
+ projectMcpServers: projectTools.mcpServers,
103
+ ...(claudeDisabled ? { machineMcp: claudeDisabled, mcpCheckout: source?.repoRoot ?? repoRoot } : {}),
104
+ }
105
+ : fencedMount ? { mcpArgs: fencedMount.args } : {},
106
+ };
107
+ } catch (e) {
108
+ projectTools.cleanup();
109
+ throw e;
110
+ }
111
+ }