@nac3/forge-cli 1.0.49 → 1.0.51

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 (66) hide show
  1. package/dist/chat/agent_scope.d.ts +41 -0
  2. package/dist/chat/agent_scope.d.ts.map +1 -0
  3. package/dist/chat/agent_scope.js +80 -0
  4. package/dist/chat/agent_scope.js.map +1 -0
  5. package/dist/chat/agent_session.d.ts +46 -0
  6. package/dist/chat/agent_session.d.ts.map +1 -0
  7. package/dist/chat/agent_session.js +169 -0
  8. package/dist/chat/agent_session.js.map +1 -0
  9. package/dist/chat/bridge.d.ts +8 -0
  10. package/dist/chat/bridge.d.ts.map +1 -1
  11. package/dist/chat/bridge.js +8 -3
  12. package/dist/chat/bridge.js.map +1 -1
  13. package/dist/chat/claude_cli.d.ts.map +1 -1
  14. package/dist/chat/claude_cli.js +7 -0
  15. package/dist/chat/claude_cli.js.map +1 -1
  16. package/dist/chat/doctrine_digest.d.ts +6 -1
  17. package/dist/chat/doctrine_digest.d.ts.map +1 -1
  18. package/dist/chat/doctrine_digest.js +7 -2
  19. package/dist/chat/doctrine_digest.js.map +1 -1
  20. package/dist/chat/panel.d.ts.map +1 -1
  21. package/dist/chat/panel.js +104 -7
  22. package/dist/chat/panel.js.map +1 -1
  23. package/dist/chat/server.d.ts +20 -1
  24. package/dist/chat/server.d.ts.map +1 -1
  25. package/dist/chat/server.js +58 -7
  26. package/dist/chat/server.js.map +1 -1
  27. package/dist/chat/tools/nac3_invoke.d.ts.map +1 -1
  28. package/dist/chat/tools/nac3_invoke.js +57 -1
  29. package/dist/chat/tools/nac3_invoke.js.map +1 -1
  30. package/dist/chat/tools/session_verbs.d.ts +39 -0
  31. package/dist/chat/tools/session_verbs.d.ts.map +1 -0
  32. package/dist/chat/tools/session_verbs.js +299 -0
  33. package/dist/chat/tools/session_verbs.js.map +1 -0
  34. package/dist/chat/tools.d.ts.map +1 -1
  35. package/dist/chat/tools.js +16 -0
  36. package/dist/chat/tools.js.map +1 -1
  37. package/dist/commands/chat.d.ts +14 -0
  38. package/dist/commands/chat.d.ts.map +1 -1
  39. package/dist/commands/chat.js +80 -1
  40. package/dist/commands/chat.js.map +1 -1
  41. package/dist/core/limits_config.d.ts +10 -0
  42. package/dist/core/limits_config.d.ts.map +1 -1
  43. package/dist/core/limits_config.js +9 -0
  44. package/dist/core/limits_config.js.map +1 -1
  45. package/dist/docs/doctrine/session-orchestration.md +86 -0
  46. package/dist/nac3/internal_manifest.d.ts.map +1 -1
  47. package/dist/nac3/internal_manifest.js +103 -0
  48. package/dist/nac3/internal_manifest.js.map +1 -1
  49. package/dist/nac3/manifest_lazy.d.ts +5 -0
  50. package/dist/nac3/manifest_lazy.d.ts.map +1 -1
  51. package/dist/nac3/manifest_lazy.js +3 -3
  52. package/dist/nac3/manifest_lazy.js.map +1 -1
  53. package/dist/version.d.ts +1 -1
  54. package/dist/version.js +1 -1
  55. package/docs/doctrine/session-orchestration.md +86 -0
  56. package/package.json +1 -1
  57. package/src/i18n/catalogs/ar.json +1 -0
  58. package/src/i18n/catalogs/de.json +1 -0
  59. package/src/i18n/catalogs/en.json +1 -0
  60. package/src/i18n/catalogs/es.json +1 -0
  61. package/src/i18n/catalogs/fr.json +1 -0
  62. package/src/i18n/catalogs/hi.json +1 -0
  63. package/src/i18n/catalogs/it.json +1 -0
  64. package/src/i18n/catalogs/ja.json +1 -0
  65. package/src/i18n/catalogs/pt.json +1 -0
  66. package/src/i18n/catalogs/zh.json +1 -0
@@ -261,7 +261,9 @@ export async function startChatServer(opts) {
261
261
  * ephemeral runs (vitest sets VITEST; also skip an obvious temp root). */
262
262
  const isTestEnv = !!process.env.VITEST || process.env.NODE_ENV === 'test';
263
263
  const isTempRoot = /[\\/](?:te?mp|yf-[a-z-]*proj|yf-startup)/i.test(opts.projectRoot);
264
- if (!isTestEnv && !isTempRoot) {
264
+ /* A headless agent sub-session must NEVER touch the global registry --
265
+ * it would flip the parent's active project (Pablo's scramble bug). */
266
+ if (!isTestEnv && !isTempRoot && !opts.agentMode) {
265
267
  void (async () => {
266
268
  try {
267
269
  await upsertProject({ slug: projectSlug, path: opts.projectRoot });
@@ -439,7 +441,12 @@ export async function startChatServer(opts) {
439
441
  * so if the user pairs a phone MID-SESSION it wakes up automatically (no
440
442
  * restart needed). When the relay is off it is a cheap no-op timer. */
441
443
  let commandConsumerHandle = null;
444
+ /* A headless agent sub-session does NOT consume phone commands -- every
445
+ * yf chat polls the same relay stream, so a child would race the parent
446
+ * for ownership and could run a mobile command twice. */
442
447
  try {
448
+ if (opts.agentMode)
449
+ throw new Error('agent-mode: relay consumer disabled');
443
450
  commandConsumerHandle = startDesktopCommandConsumer(opts.port, {
444
451
  /* live so a reanchor moves which commands this instance owns */
445
452
  getActiveSlug: () => session.projectSlug,
@@ -525,6 +532,7 @@ export async function startChatServer(opts) {
525
532
  url,
526
533
  port: opts.port,
527
534
  store,
535
+ bridge: bridgeHandle,
528
536
  close: () => new Promise((resolve) => {
529
537
  /* alpha.59w -- stop the component watcher on shutdown so
530
538
  * vitest does not hang on lingering fs watchers. */
@@ -3771,6 +3779,11 @@ async function handleStartupTabs(_req, res, ctx, url) {
3771
3779
  const gNodes = nodes.map((n) => ({ id: n.id, label: n.name || n.id, weight: n.weight, kind: n.kind, confidence: n.confidence, detail: n.purpose || '' }));
3772
3780
  const gEdges = edges.map((e) => ({ from: e.from_id, to: e.to_id, kind: e.kind }));
3773
3781
  tabs.push({ key: 'startup_graph', title: t('startup.tab.graph'), kind: 'graph', content: JSON.stringify({ nodes: gNodes, edges: gEdges }) });
3782
+ /* Vista funcional -- misma data, marcada mode:'functional'. El panel
3783
+ * la renderiza centrada en las funcionalidades de front-end (nodos
3784
+ * del grupo 'frontend') con un selector para filtrar el subgrafo que
3785
+ * cada funcionalidad toca. Reusa el mismo renderer de grafo. */
3786
+ tabs.push({ key: 'startup_graph_func', title: t('startup.tab.graphFunc'), kind: 'graph', content: JSON.stringify({ nodes: gNodes, edges: gEdges, mode: 'functional' }) });
3774
3787
  /* Grafo semantico = misma data en markdown (tabla de nodos por
3775
3788
  * peso + conteo de aristas), con la confianza para distinguir lo
3776
3789
  * declarado (claimed) de lo derivado del codigo (auto). */
@@ -5013,6 +5026,16 @@ async function handleChat(req, res, ctx) {
5013
5026
  mcpAvailable = bridges.some((b) => b.enabled);
5014
5027
  }
5015
5028
  catch (_) { /* registry failure -> stay with MCP-off behaviour */ }
5029
+ /* Multi-agent session orchestration toggle (Pablo 2026-06-28). Default
5030
+ * OFF: the yujin.session.* verbs + their doctrine are hidden from the
5031
+ * prompt and the brain is told the feature is off. The user opts in via
5032
+ * Ajustes > Limites (multiagent.enabled). */
5033
+ let multiagentEnabled = false;
5034
+ try {
5035
+ const { readLimitsConfig } = await import('../core/limits_config.js');
5036
+ multiagentEnabled = (await readLimitsConfig()).multiagent.enabled === true;
5037
+ }
5038
+ catch (_) { /* config failure -> stay OFF (safe default) */ }
5016
5039
  /* alpha.59z.37 NAC-3 v3.x backend tools -- prefetch the
5017
5040
  * adopter app's nac3_backend section (task #23). Empty
5018
5041
  * string when the manifest does not declare it, when the
@@ -5141,7 +5164,7 @@ async function handleChat(req, res, ctx) {
5141
5164
  * pizarron_create_tab tool; in API/managed it is native. */
5142
5165
  ctx.chatProvider === 'claude-code-cli'
5143
5166
  ? (ctx.panelPushToken ? 'mcp-bridge' : 'none')
5144
- : 'native', projectIdentity),
5167
+ : 'native', projectIdentity, multiagentEnabled),
5145
5168
  systemDynamic: recentSessionsRecap + projectContextSection + snapshotSection + graphSection + wiringSection + toolingSection + workflowSection + approvalPostureSection,
5146
5169
  maxTokens: _maxTokensPerTurn,
5147
5170
  /* Plan/CLI uses Claude Code's native tools (FORGE_TOOL_SPECS = just
@@ -5341,7 +5364,7 @@ async function handleChat(req, res, ctx) {
5341
5364
  model: frontierSel.model,
5342
5365
  }, globalLearnings, mcpAvailable, backendToolsSection, lastUserText, ctx.chatProvider === 'claude-code-cli'
5343
5366
  ? (ctx.panelPushToken ? 'mcp-bridge' : 'none')
5344
- : 'native', projectIdentity),
5367
+ : 'native', projectIdentity, multiagentEnabled),
5345
5368
  };
5346
5369
  const frontierReply = await frontierCaller.chat(frontierRequest);
5347
5370
  reply = frontierReply;
@@ -5800,7 +5823,12 @@ panelMode = 'native',
5800
5823
  * CLI version with the project's own version (Pablo: "Es Forge v1.0.44"
5801
5824
  * appeared while anchored to Yuemail 0.6.4). Undefined -> the block
5802
5825
  * falls back to name + root + Forge-CLI version (back-compat). */
5803
- projectIdentity) {
5826
+ projectIdentity,
5827
+ /** Pablo 2026-06-28 -- whether multi-agent session orchestration
5828
+ * (yujin.session.*) is enabled in config. When false (default) the
5829
+ * session verbs + their doctrine line are filtered out and the brain is
5830
+ * told the feature is OFF. The caller prefetches readLimitsConfig(). */
5831
+ multiagentEnabled = false) {
5804
5832
  /* alpha.58 -- tier awareness header. When the request is
5805
5833
  * served by an eco-tier model (Gemini Flash Lite, Haiku),
5806
5834
  * the model is told its role explicitly so it can be more
@@ -5830,7 +5858,7 @@ projectIdentity) {
5830
5858
  'tengo los verbos NAC-3 enchufados" is FACTUALLY WRONG -- your',
5831
5859
  'runtime DOES have the NAC-3 manifest wired (yujin.fs.*,',
5832
5860
  'yujin.git.*, yujin.graph.*, yujin.wiring.*, yujin.pending.*,',
5833
- 'yujin.doctrine.*, yujin.nac3.*, yujin.bridge.*, plus the rest in',
5861
+ 'yujin.doctrine.*, yujin.nac3.*, yujin.bridge.*, yujin.session.*, plus the rest in',
5834
5862
  'the manifest stub below). When in doubt about what is available, call',
5835
5863
  'yujin.manifest.read or yujin.nac3.discover-schemas before',
5836
5864
  'claiming "no tengo X". Falsely claiming otherwise destroys',
@@ -6066,8 +6094,23 @@ projectIdentity) {
6066
6094
  ' yujin.shell.exec is for ops with NO native verb equivalent:',
6067
6095
  ' npm install, docker build, pytest, custom scripts, etc.',
6068
6096
  '',
6097
+ /* Multi-agent orchestration state (Pablo 2026-06-28) -- the brain must
6098
+ * KNOW whether yujin.session.* is available. Default OFF. */
6099
+ ...(multiagentEnabled
6100
+ ? [
6101
+ 'ORQUESTACION MULTIAGENTE: ON. Podes lanzar sub-sesiones `yf chat`',
6102
+ 'headless con yujin.session.spawn para tareas ORTOGONALES en paralelo',
6103
+ '(ver la doctrina session-orchestration). Siempre yujin.session.collect',
6104
+ 'lo que lances.', '',
6105
+ ]
6106
+ : [
6107
+ 'ORQUESTACION MULTIAGENTE: OFF. Los verbos yujin.session.* NO estan',
6108
+ 'disponibles en esta sesion (no figuran en el manifest). No intentes',
6109
+ 'lanzar sub-sesiones. Si el usuario quiere paralelizar con sub-sesiones,',
6110
+ 'decile que la active en Ajustes > Limites (multiagent.enabled).', '',
6111
+ ]),
6069
6112
  'MANIFEST:',
6070
- buildManifestForPrompt({ includeMcpVerbs: mcpAvailable }).text,
6113
+ buildManifestForPrompt({ includeMcpVerbs: mcpAvailable, includeSessionVerbs: multiagentEnabled }).text,
6071
6114
  /* alpha.59z.37 NAC-3 v3.x backend tools (task #23 slice 1):
6072
6115
  * splice the pre-built app.* verbs section. Empty string ->
6073
6116
  * nothing appears (Invariant: identical to v3.0 when no
@@ -6083,7 +6126,7 @@ projectIdentity) {
6083
6126
  * code-quality guardrails, so the condensed essence of EVERY one
6084
6127
  * is injected mandatorily in every prompt (not on-demand). Full
6085
6128
  * text still on-demand via yujin.doctrine.discover. */
6086
- ...buildDoctrineDigestLines(),
6129
+ ...buildDoctrineDigestLines({ includeSession: multiagentEnabled }),
6087
6130
  '=================================================================',
6088
6131
  'PIZARRON DOCTRINE (condensed; full text on-demand)',
6089
6132
  '=================================================================',
@@ -6267,6 +6310,14 @@ projectIdentity) {
6267
6310
  'For the full doctrine with MAL/BIEN examples, call',
6268
6311
  'yujin.doctrine.discover({slugs:["r8-modal"]}).',
6269
6312
  '',
6313
+ 'R9 -- ASK AND STOP (twin of R8, for a USER DECISION): when you',
6314
+ 'truly need the user to decide/clarify, STOP and ask it as your',
6315
+ 'FINAL message in plain prose -- no tool after the question, no',
6316
+ 'proceeding on a guess, never "I will proceed with X" when X is',
6317
+ 'what you needed decided. Do NOT call AskUserQuestion/popups',
6318
+ '(non-interactive here -> lost). Prose as the last thing you say',
6319
+ 'IS the question; the user answers next turn. Do not overuse.',
6320
+ '',
6270
6321
  '=================================================================',
6271
6322
  'BYOK + LICENSE (all chat/voice -- LEMA YUJIN)',
6272
6323
  '=================================================================',