@nac3/forge-cli 1.3.2 → 1.3.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"doctrine_digest.d.ts","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,eAAe,EAAE,mBAAmB,EA2IhD,CAAC;AAEF,6DAA6D;AAC7D,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAED,MAAM,WAAW,qBAAqB;IACpC;4EACwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;uEACuE;AACvE,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,EAAE,CAiBnF"}
1
+ {"version":3,"file":"doctrine_digest.d.ts","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,eAAe,EAAE,mBAAmB,EAwHhD,CAAC;AAEF,6DAA6D;AAC7D,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC;AAED,MAAM,WAAW,qBAAqB;IACpC;4EACwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;uEACuE;AACvE,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,EAAE,CAiBnF"}
@@ -53,7 +53,7 @@ export const DOCTRINE_DIGEST = [
53
53
  },
54
54
  {
55
55
  slugs: ['workflow-kinds'],
56
- rule: 'THREE kinds: greenfield (new app) / corrective (fix a live project) / evolutive (extend one). Open one with yujin.workflow.start -- it classifies, and on needs_confirm ASK the user the kind, then spawns the task pendings IN ORDER. Tasks ARE pendings (stages are not); close them in order; the workflow auto-closes when all close. Add ad-hoc tasks mid-run with yujin.workflow.add-task. corrective/evolutive MUST refresh docs.',
56
+ rule: 'THREE kinds: greenfield / corrective / evolutive. Open with yujin.workflow.start (classifies; on needs_confirm ASK the kind), which spawns task-pendings IN ORDER (tasks ARE pendings, stages are not). Close in order; auto-closes when all close; add ad-hoc with add-task. corrective/evolutive MUST refresh docs.',
57
57
  },
58
58
  {
59
59
  slugs: ['g-doc'],
@@ -77,58 +77,39 @@ export const DOCTRINE_DIGEST = [
77
77
  },
78
78
  {
79
79
  slugs: ['diagnostic-mode'],
80
- rule: 'every project you build can ship a RESIDENT assistant -- when you create '
81
- + 'or finish a project, OFFER to embed it (yf embed / generateEmbedScaffold: '
82
- + 'writes .forge/profile.prod+uat.json + mission.md + db.json.example + '
83
- + 'systemd units; committed but inert until the server sets YF_ENV=prod|uat). '
84
- + 'ENRICH mission.md from the app\'s real config surface + support cases. '
85
- + 'When you ARE the read-only embedded assistant: diagnose with evidence, '
86
- + 'query via yujin.db.query (SELECT-only, never shell mysql nor invent an '
87
- + 'HTTP endpoint), emit precise operator instructions, write reports under '
88
- + 'docs/ or .forge/diagnostics/, and stay pinned (no writes/switch/push). '
89
- + 'DURABLE SYSTEM MAP: keep .forge/diagnostics/system-map.md (identity, '
90
- + 'environments, components, lifecycle, DB schemas+live counts, key files, '
91
- + 'jobs, secrets, diagnostic playbook, rules, semantic graph). The server '
92
- + 'injects it as ground truth; if it is MISSING, BUILD it before diagnosing; '
93
- + 'READ it first every session (never re-discover from scratch) and refresh '
94
- + 'it when stale.',
80
+ rule: 'RESIDENT assistant: when you finish a project, OFFER to embed it (yf embed). '
81
+ + 'When you ARE the read-only embedded assistant: diagnose with evidence, query '
82
+ + 'via yujin.db.query (SELECT-only, never shell mysql nor invented HTTP), write '
83
+ + 'reports under docs/.forge, stay pinned (no writes/switch/push). Keep + '
84
+ + 'READ-FIRST .forge/diagnostics/system-map.md (server injects it as ground '
85
+ + 'truth; BUILD it if missing, refresh when stale). Full: discover.',
95
86
  },
96
87
  {
97
88
  slugs: ['concurrency-scale'],
98
- rule: 'size every app to its expected CONCURRENCY from the start: during '
99
- + 'relevamiento ASK peak simultaneous users / read-vs-write / latency '
100
- + 'budget / growth (if unknown, assume a default and WRITE it in the '
101
- + 'spec), then choose a multi-layer design that has no bottleneck at any '
102
- + 'tier -- stateless app nodes (scale out), connection pools + queues / '
103
- + 'backpressure for spikes, cache hot reads, read replicas / async jobs '
104
- + 'for the data tier, broker fan-out for realtime -- PROPORTIONAL to the '
105
- + 'number (a 20-user tool stays single-tier; neither a bottleneck nor '
106
- + 'gold-plating).',
89
+ rule: 'size every app to its expected CONCURRENCY: in relevamiento ASK peak '
90
+ + 'simultaneous users / read-vs-write / latency / growth (unknown -> assume a '
91
+ + 'default and WRITE it in the spec); design with no bottleneck at any tier, '
92
+ + 'PROPORTIONAL to the number (a 20-user tool stays single-tier; no '
93
+ + 'gold-plating). Full: discover.',
107
94
  },
108
95
  {
109
96
  slugs: ['performance-hardening'],
110
- rule: 'harden every load-bearing component for its load in v1 -- match the '
111
- + 'trigger (full patterns via discover): DB batch = COMMIT PER CHUNK, '
112
- + 'never a tx open across a network call, deadlock retry w/ backoff but '
113
- + 'never an external call inside a retry; third parties NON-idempotent -- '
114
- + 'dedupe by id ON WRITE (UNIQUE), ACK-first + background, pace outbound, '
115
- + 'firm reject -> dead-end not retry-burst; background loops = '
116
- + 'backpressure cap per pass + TTL-keyed locks + start-once singletons; '
117
- + 'lists PAGINATE server-side; growing tables INDEX filtered/sorted cols, '
118
- + 'no fn on an indexed col, no LIKE %q%, VARCHAR(191) not TEXT; long work '
119
- + '-> job+poll not a 504; TTL-clean growth; heartbeat+watchdog+'
120
- + 'alert-dedupe. LAWS: cero hardcode (thresholds in config, default '
121
- + 'preserves behavior, dangerous features born inert), producer/consumer '
122
- + 'symmetry, fail-closed, MEASURE before a fan-out switch, PROPORTIONAL '
123
- + '(pairs with concurrency-scale).',
97
+ rule: 'harden every load-bearing component for its v1 load (full patterns via '
98
+ + 'discover): DB batch = commit-per-chunk, never a tx across a network call; '
99
+ + 'third-party writes idempotent (dedupe by id on write, ACK-first+background, '
100
+ + 'pace, firm-reject not retry-burst); background loops backpressured + TTL '
101
+ + 'locks + start-once; paginate lists; index filtered/sorted cols (no fn on an '
102
+ + 'indexed col, no LIKE %q%); long work = job+poll; TTL-clean growth; '
103
+ + 'heartbeat+watchdog. LAWS: zero-hardcode, producer/consumer symmetry, '
104
+ + 'fail-closed, MEASURE before a fan-out switch, PROPORTIONAL.',
124
105
  },
125
106
  {
126
107
  slugs: ['verb-composition'],
127
- rule: 'compose native verbs in dependency order; prefer a yujin.* verb over shell. The harness does NOT persist once you reply: run FOREGROUND or via a Forge durable channel. Long-running/background work (dev server/watcher/tunnel/test suite -- anything outliving THIS reply) MUST use yujin.task.run, NOT shell.exec (refuses them) nor native Bash run_in_background (blocked). Orthogonal parallelism -> yujin.session.spawn, NOT native Task/Agent (blocked). Track via yujin.task.status/list.',
108
+ rule: 'compose native verbs in dependency order; prefer yujin.* over shell. The harness does NOT persist after you reply: long-running/background work (dev server/watcher/tunnel/test suite) MUST use yujin.task.run (not shell.exec nor native Bash run_in_background -- both blocked); orthogonal parallelism -> yujin.session.spawn (not native Task/Agent). Track via yujin.task.status/list.',
128
109
  },
129
110
  {
130
111
  slugs: ['pizarron'],
131
- rule: 'create-tab = canvas content YOU generated; open-file = a disk file; opening a file is NOT saving it. KIND SELECTION (mandatory, classify BEFORE create-tab): FLUJO/flujo/flowchart/proceso/circuito/"los pasos de"/BPMN -> kind=bpmn (BPMN 2.0); PROHIBIDO kind=graph para un proceso. Relaciones/dependencias/"que usa que"/grafo del proyecto -> kind=graph (el grafo es para relaciones sin orden, no procesos). DOCUMENTO/reporte/spec/analisis/diseño/arquitectura -> kind=doc con content en HTML por DEFAULT (h1/h2/p/ul/table/etc.; sin <script>/<style>), NO texto plano ni markdown salvo pedido. Codigo -> kind=code. Duda bpmn vs graph: tiene inicio, fin y pasos en orden? -> bpmn. JS de verdad (viz/herramienta) -> kind=app (iframe sandbox aislado), NUNCA para documentos. PERSISTENCIA AUTOMATICA (PND-134): create-tab con kind doc/document/md/html/table se guarda solo en docs/<slug>.(html|md), y kind bpmn/flow se guarda solo como docs/flows/<slug>.svg (grafico) + .bpmn.json (fuente). NO necesitas un write-project-file extra para eso: clasificar bien el kind YA deja el archivo en el repo. LANES (bpmn): NO declares una lane que no vas a poblar -- cada lane declarada DEBE tener >=1 nodo. Modela al actor que RESPONDE en SU propia lane: si un actor recibe una propuesta/solicitud, incluí su paso (aceptar/rechazar/responder) en la lane de ESE actor, no en la de Sistema.',
112
+ rule: 'create-tab = content YOU generated; open-file = a disk file (opening != saving). Kind selection (FLUJO/proceso -> kind=bpmn NEVER kind=graph; relations/dependencies -> kind=graph; doc/report/spec -> kind=doc in HTML; code -> kind=code; real JS viz -> kind=app) + auto-persist to docs/: full table in the PIZARRON DOCTRINE section above -- do not restate. LANES (bpmn): every declared lane needs >=1 node; model the RESPONDING actor (accept/reject/reply) in ITS OWN lane, not Sistema.',
132
113
  },
133
114
  {
134
115
  slugs: ['r8-modal'],
@@ -144,7 +125,7 @@ export const DOCTRINE_DIGEST = [
144
125
  },
145
126
  {
146
127
  slugs: ['office-tools'],
147
- rule: 'office docs (.xlsx/.xls/.csv/.docx/.pdf): to OPEN/show one to the user use desktop.open({target}) (-> Excel/Word/the viewer; a Google Sheets URL -> the browser); to read/compute its DATA use office.excel.read / office.word.read. NEVER fs.read-file or open-file on a binary office file (renders as noise and FREEZES the panel) and NEVER shell out to python/pandas/openpyxl.',
128
+ rule: 'office docs (.xlsx/.csv/.docx/.pdf): to OPEN/show one use desktop.open({target}); to read/compute its DATA use office.excel.read / office.word.read. NEVER fs.read-file/open-file on a binary office file (renders as noise + FREEZES the panel) and NEVER shell to python/pandas/openpyxl.',
148
129
  },
149
130
  {
150
131
  slugs: ['mcp-bridge-lifecycle', 'expo-eas-builds', 'agent-orchestrator', 'yf-commands', 'lessons-workflow'],
@@ -1 +1 @@
1
- {"version":3,"file":"doctrine_digest.js","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctrine_digest.js","sourceRoot":"","sources":["../../src/chat/doctrine_digest.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"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"}
@@ -640,6 +640,23 @@ export async function startChatServer(opts) {
640
640
  function relayEnabled() {
641
641
  return relayGate(process.env.YF_RELAY, isMobilePaired());
642
642
  }
643
+ /* Panel SSE fan-out (2026-09-09). The CLI/Plan bridge (a verb dispatch from the
644
+ * `claude` subprocess) runs in a SEPARATE HTTP request from the chat SSE stream,
645
+ * so it had no `sseEmit` in scope and could NOT open the R8 approval modal --
646
+ * destructive/approval-required verbs were enqueued (awaiting_user_approval in
647
+ * the log) but no modal ever showed; the brain narrated "aprobalo en el modal"
648
+ * while nothing appeared (Pablo 2026-09-09). Register each LIVE chat SSE emitter
649
+ * here so the bridge can broadcast `approval_required` to the panel, exactly as
650
+ * the HTTP path does inline. */
651
+ const panelSseEmitters = new Set();
652
+ function broadcastToPanel(event, data) {
653
+ for (const emit of panelSseEmitters) {
654
+ try {
655
+ emit(event, data);
656
+ }
657
+ catch { /* best-effort */ }
658
+ }
659
+ }
643
660
  let _relayPub = null;
644
661
  function getRelayPublisher() {
645
662
  if (!relayEnabled())
@@ -3982,6 +3999,12 @@ async function handlePanelInvoke(req, res, ctx) {
3982
3999
  * modal sincronicamente; le decimos que el usuario debe aprobar.
3983
4000
  * NO se ejecuta la accion destructiva sin aprobacion. */
3984
4001
  if (result.nac3_panel_approval_required === true) {
4002
+ /* Open the R8 modal on the panel NOW: the bridge runs in its own HTTP
4003
+ * request, so we broadcast the approval envelope to the live chat SSE
4004
+ * stream (the HTTP path does this inline at the tool-loop). Without this
4005
+ * the verb sat enqueued (awaiting_user_approval) but no modal ever showed
4006
+ * on the Plan/CLI path (Pablo 2026-09-09). */
4007
+ broadcastToPanel('approval_required', result);
3985
4008
  sendJson(res, 200, {
3986
4009
  ok: false, approval_required: true,
3987
4010
  text: 'Esta accion requiere aprobacion del usuario en el panel de Forge. '
@@ -5186,6 +5209,14 @@ async function handleChat(req, res, ctx) {
5186
5209
  sseWrite(event, data);
5187
5210
  relayForward(event, data);
5188
5211
  };
5212
+ /* Register this live emitter so out-of-turn producers -- notably the CLI/Plan
5213
+ * bridge dispatching verbs from the subprocess -- can push events (e.g.
5214
+ * approval_required to open the R8 modal) to the panel. Unregister on
5215
+ * disconnect so a stale stream is never written to. */
5216
+ if (streamMode) {
5217
+ panelSseEmitters.add(sseEmit);
5218
+ res.on('close', () => { panelSseEmitters.delete(sseEmit); });
5219
+ }
5189
5220
  /* alpha.51 -- session-level brain tier override from slash
5190
5221
  * commands (/eco /frontier /auto). null = let cost_router
5191
5222
  * decide per-turn. The router reads workflow state + verb
@@ -5685,7 +5716,14 @@ async function handleChat(req, res, ctx) {
5685
5716
  ctx.chatProvider === 'claude-code-cli'
5686
5717
  ? (ctx.panelPushToken ? 'mcp-bridge' : 'none')
5687
5718
  : 'native', projectIdentity, multiagentEnabled),
5688
- systemDynamic: recentSessionsRecap + projectContextSection + snapshotSection + graphSection + wiringSection + toolingSection + workflowSection + approvalPostureSection + toolStatusSection(),
5719
+ /* Prompt audit A (2026-09-09): order STABLE sections first (project
5720
+ * context, wiring, tooling, recent-sessions -- unchanged within a
5721
+ * session) and VOLATILE ones last (graph/snapshot hashes, workflow state,
5722
+ * live tool-status timestamp). The static prompt is the cached prefix; a
5723
+ * stable-first suffix lets a prefix cache extend through the unchanged
5724
+ * dynamic lines instead of missing on the first per-turn byte. ~84% of
5725
+ * this block was byte-identical turn-to-turn yet re-sent uncached. */
5726
+ systemDynamic: projectContextSection + wiringSection + toolingSection + recentSessionsRecap + graphSection + snapshotSection + workflowSection + approvalPostureSection + toolStatusSection(),
5689
5727
  maxTokens: _maxTokensPerTurn,
5690
5728
  /* Plan/CLI uses Claude Code's native tools (FORGE_TOOL_SPECS = just
5691
5729
  * nac3_invoke via the MCP bridge); the HTTP path (BYOK/Console + managed)
@@ -6936,25 +6974,25 @@ multiagentEnabled = false) {
6936
6974
  * strict config so the model only mentions approval when a modal will really
6937
6975
  * appear. Read per-turn -> toggling the switch takes effect next turn. */
6938
6976
  export function buildApprovalPostureSection(autoApprove, cwdStrict) {
6939
- return '\n\n=================================================================\n'
6940
- + 'RUNTIME APPROVAL POSTURE (live config -- this OVERRIDES R8)\n'
6941
- + '=================================================================\n'
6942
- + (autoApprove
6943
- ? '- danger_zone.auto_approve_all = TRUE (autonomous mode). Destructive\n'
6944
- + ' verbs (git push/commit, rm, fs.write-project-file, shell.exec, ...)\n'
6945
- + ' EXECUTE IMMEDIATELY with NO approval modal. Do NOT tell the user to\n'
6946
- + ' approve anything, and do NOT say "a modal will appear" -- none does.\n'
6947
- + ' Just invoke the verb and report the result. (This SUSPENDS R8 while ON.)\n'
6948
- : '- danger_zone.auto_approve_all = FALSE. Destructive verbs open a native\n'
6949
- + ' Approve/Reject MODAL the user must accept (R8 applies). The modal IS\n'
6950
- + ' the question: invoke the verb, let the modal appear, do NOT re-ask in\n'
6951
- + ' chat. At most one short line that approval is pending.\n')
6952
- + (cwdStrict
6953
- ? '- shell.cwd_boundary_strict = TRUE. Shell is confined to the project\n'
6954
- + ' root; commands targeting paths outside it are blocked.\n'
6955
- : '- shell.cwd_boundary_strict = FALSE. Shell may operate outside the\n'
6956
- + ' project root.\n')
6957
- + 'Never describe approval behavior that contradicts the two lines above.';
6977
+ /* Prompt audit E (2026-09-09): only inject a posture block when the LIVE config
6978
+ * DEVIATES from the static R8 default (destructive verbs open a modal; shell
6979
+ * free). When it matches R8 -- the common case -- say nothing: repeating "a
6980
+ * modal opens" and "this OVERRIDES R8" every turn just diluted R8 and burned
6981
+ * ~120 tok/turn. The block appears only for the real overrides. */
6982
+ if (!autoApprove && !cwdStrict)
6983
+ return '';
6984
+ const lines = ['\n\nRUNTIME APPROVAL POSTURE (live config -- deviates from the R8 default):'];
6985
+ if (autoApprove) {
6986
+ lines.push('- danger_zone.auto_approve_all = TRUE (autonomous). Destructive verbs '
6987
+ + '(git push/commit, rm, fs.write-project-file, shell.exec, ...) EXECUTE '
6988
+ + 'IMMEDIATELY with NO approval modal -- this SUSPENDS R8. Do NOT tell the user '
6989
+ + 'to approve or say "a modal appears"; just invoke and report.');
6990
+ }
6991
+ if (cwdStrict) {
6992
+ lines.push('- shell.cwd_boundary_strict = TRUE. Shell is confined to the project '
6993
+ + 'root; commands targeting paths outside it are blocked.');
6994
+ }
6995
+ return lines.join('\n');
6958
6996
  }
6959
6997
  function sendJson(res, status, body) {
6960
6998
  res.statusCode = status;