@nac3/forge-cli 1.26.0 → 1.28.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.
Files changed (93) hide show
  1. package/dist/chat/graph_snapshot.d.ts +24 -0
  2. package/dist/chat/graph_snapshot.d.ts.map +1 -1
  3. package/dist/chat/graph_snapshot.js +28 -3
  4. package/dist/chat/graph_snapshot.js.map +1 -1
  5. package/dist/chat/history_budget.d.ts +114 -0
  6. package/dist/chat/history_budget.d.ts.map +1 -0
  7. package/dist/chat/history_budget.js +98 -0
  8. package/dist/chat/history_budget.js.map +1 -0
  9. package/dist/chat/panel.d.ts.map +1 -1
  10. package/dist/chat/panel.js +26 -0
  11. package/dist/chat/panel.js.map +1 -1
  12. package/dist/chat/server.d.ts.map +1 -1
  13. package/dist/chat/server.js +59 -1
  14. package/dist/chat/server.js.map +1 -1
  15. package/dist/chat/tools/pending.d.ts.map +1 -1
  16. package/dist/chat/tools/pending.js +25 -10
  17. package/dist/chat/tools/pending.js.map +1 -1
  18. package/dist/chat/tools/pending_ack.d.ts +82 -0
  19. package/dist/chat/tools/pending_ack.d.ts.map +1 -0
  20. package/dist/chat/tools/pending_ack.js +55 -0
  21. package/dist/chat/tools/pending_ack.js.map +1 -0
  22. package/dist/chat/tools/reader.d.ts.map +1 -1
  23. package/dist/chat/tools/reader.js +24 -4
  24. package/dist/chat/tools/reader.js.map +1 -1
  25. package/dist/commands/operate.d.ts.map +1 -1
  26. package/dist/commands/operate.js +42 -0
  27. package/dist/commands/operate.js.map +1 -1
  28. package/dist/commands/urazuke.d.ts.map +1 -1
  29. package/dist/commands/urazuke.js +189 -9
  30. package/dist/commands/urazuke.js.map +1 -1
  31. package/dist/core/instructions_budget.d.ts +113 -0
  32. package/dist/core/instructions_budget.d.ts.map +1 -0
  33. package/dist/core/instructions_budget.js +165 -0
  34. package/dist/core/instructions_budget.js.map +1 -0
  35. package/dist/core/limits_config.d.ts +23 -0
  36. package/dist/core/limits_config.d.ts.map +1 -1
  37. package/dist/core/limits_config.js +36 -0
  38. package/dist/core/limits_config.js.map +1 -1
  39. package/dist/core/machine_files.d.ts +27 -0
  40. package/dist/core/machine_files.d.ts.map +1 -0
  41. package/dist/core/machine_files.js +97 -0
  42. package/dist/core/machine_files.js.map +1 -0
  43. package/dist/docs/doctrine/session-orchestration.md +109 -109
  44. package/dist/docs/doctrine/urazuke.md +221 -221
  45. package/dist/nac3/dispatch_log.d.ts +16 -1
  46. package/dist/nac3/dispatch_log.d.ts.map +1 -1
  47. package/dist/nac3/dispatch_log.js +29 -10
  48. package/dist/nac3/dispatch_log.js.map +1 -1
  49. package/dist/nac3/manifest_lazy.d.ts +15 -0
  50. package/dist/nac3/manifest_lazy.d.ts.map +1 -1
  51. package/dist/nac3/manifest_lazy.js +17 -1
  52. package/dist/nac3/manifest_lazy.js.map +1 -1
  53. package/dist/telemetry/battery_events.d.ts +91 -0
  54. package/dist/telemetry/battery_events.d.ts.map +1 -0
  55. package/dist/telemetry/battery_events.js +84 -0
  56. package/dist/telemetry/battery_events.js.map +1 -0
  57. package/dist/telemetry/usage.d.ts.map +1 -1
  58. package/dist/telemetry/usage.js +11 -25
  59. package/dist/telemetry/usage.js.map +1 -1
  60. package/dist/urazuke/evidence.d.ts.map +1 -1
  61. package/dist/urazuke/evidence.js +14 -2
  62. package/dist/urazuke/evidence.js.map +1 -1
  63. package/dist/urazuke/freeze.d.ts.map +1 -1
  64. package/dist/urazuke/freeze.js +82 -16
  65. package/dist/urazuke/freeze.js.map +1 -1
  66. package/dist/urazuke/gates_data.d.ts +4 -1
  67. package/dist/urazuke/gates_data.d.ts.map +1 -1
  68. package/dist/urazuke/gates_data.js +7 -1
  69. package/dist/urazuke/gates_data.js.map +1 -1
  70. package/dist/urazuke/gates_ledger.d.ts +25 -1
  71. package/dist/urazuke/gates_ledger.d.ts.map +1 -1
  72. package/dist/urazuke/gates_ledger.js +30 -6
  73. package/dist/urazuke/gates_ledger.js.map +1 -1
  74. package/dist/urazuke/method_config.d.ts +116 -0
  75. package/dist/urazuke/method_config.d.ts.map +1 -0
  76. package/dist/urazuke/method_config.js +328 -0
  77. package/dist/urazuke/method_config.js.map +1 -0
  78. package/dist/urazuke/prompts_client.d.ts +42 -12
  79. package/dist/urazuke/prompts_client.d.ts.map +1 -1
  80. package/dist/urazuke/prompts_client.js +120 -16
  81. package/dist/urazuke/prompts_client.js.map +1 -1
  82. package/dist/urazuke/prompts_freeze.d.ts +186 -0
  83. package/dist/urazuke/prompts_freeze.d.ts.map +1 -0
  84. package/dist/urazuke/prompts_freeze.js +498 -0
  85. package/dist/urazuke/prompts_freeze.js.map +1 -0
  86. package/dist/urazuke/start.d.ts.map +1 -1
  87. package/dist/urazuke/start.js +42 -2
  88. package/dist/urazuke/start.js.map +1 -1
  89. package/dist/version.d.ts +1 -1
  90. package/dist/version.js +1 -1
  91. package/docs/doctrine/session-orchestration.md +109 -109
  92. package/docs/doctrine/urazuke.md +221 -221
  93. package/package.json +125 -124
@@ -0,0 +1,328 @@
1
+ /**
2
+ * LA CONFIGURACION DEL METODO -- de donde sale la definicion, cuando avisa
3
+ * que hay una version nueva, y cuando se niega a arrancar sin congelar.
4
+ *
5
+ * Pedido del dueno, textual (2026-11-03): "y que tanto las compuertas como
6
+ * los prompts se puedan actualizar desde el config de Forge".
7
+ *
8
+ * DONDE VIVE ESTO, Y POR QUE NO EN limits.json
9
+ *
10
+ * La pregunta vino abierta ("decidilo vos y escribi por que"), asi que la
11
+ * decision esta aca y no en un commit message. Vive en el PROYECTO
12
+ * (`.forge/project-settings.json`, seccion `method`), no en el global del
13
+ * usuario, por tres razones:
14
+ *
15
+ * 1. UNA LLAVE GLOBAL QUE CAMBIA COMO SE MIDE UN PROYECTO ES INVISIBLE EN
16
+ * SU HISTORIA. El congelado de las compuertas y el de los prompts ya
17
+ * viven en `.forge/` y se commitean; la POLITICA que decide de donde
18
+ * salen tiene que viajar igual. Si estuviera en el home del usuario,
19
+ * dos maquinas darian dos veredictos del mismo commit y el diff no
20
+ * mostraria nada. Eso es exactamente la familia del cero que informaba
21
+ * salud.
22
+ * 2. YA HAY PRECEDENTE EN EL MISMO ARCHIVO. `.forge/project-settings.json`
23
+ * es donde el proyecto declara los apagados de reglas, con su registro
24
+ * de cuatro campos, y los evaluadores lo leen de ahi. La politica del
25
+ * metodo es de la misma clase: politica del proyecto que una compuerta
26
+ * consulta.
27
+ * 3. limits.json ES RUNTIME DE LA MAQUINA (topes, vencimientos, postura
28
+ * de aprobacion). Ahi SI pertenece una preferencia de maquina -- si
29
+ * este Forge avisa o no cuando sale una version nueva -- y por eso esa
30
+ * sola llave esta en limits.json (`urazuke.update_check`) y el
31
+ * proyecto la puede pisar. Ruido: maquina. Medicion: proyecto.
32
+ *
33
+ * LO QUE ESTA CONFIGURACION NO PUEDE HACER, Y ES EL LIMITE DE TODO ESTO
34
+ *
35
+ * Ninguna llave de configuracion puede adoptar una version sin la razon
36
+ * escrita del dueno.
37
+ *
38
+ * Si se pudiera declarar "adopta siempre lo ultimo", el doble candado se
39
+ * termino: el proyecto cambiaria lo que el agente lee en cada turno sin que
40
+ * nadie firme el cambio. La configuracion puede decir DE DONDE MIRAR,
41
+ * CUANDO AVISAR y CUANDO NEGARSE A ARRANCAR. La adopcion sigue siendo un
42
+ * acto con nombre y razon (`gates adopt --reason`, `prompts adopt
43
+ * --reason`).
44
+ *
45
+ * Y no se ignora en silencio al que lo intente: una llave de
46
+ * auto-adopcion se RECHAZA con el motivo escrito (ver LLAVES_PROHIBIDAS).
47
+ * Una configuracion que descarta sin avisar es la misma familia de defecto
48
+ * que todo este lote vino a cerrar.
49
+ *
50
+ * ASCII-only.
51
+ */
52
+ import { promises as fs } from 'node:fs';
53
+ import path from 'node:path';
54
+ export const METHOD_CONFIG_REL = path.join('.forge', 'project-settings.json');
55
+ export function methodConfigPath(projectRoot) {
56
+ return path.join(projectRoot, METHOD_CONFIG_REL);
57
+ }
58
+ export const PROMPTS_SOURCES = ['frozen', 'published', 'vendored'];
59
+ export function defaultMethodConfig() {
60
+ return { prompts_source: 'frozen', strict: false };
61
+ }
62
+ /** Llaves que la configuracion NO acepta, con el motivo que se le devuelve
63
+ * a quien las escriba. La lista es explicita a proposito: el que la
64
+ * intente tiene que leer por que no, no descubrir que no paso nada. */
65
+ export const LLAVES_PROHIBIDAS = {
66
+ auto_adopt: 'la adopcion es un acto con autor y razon escrita (yf urazuke gates|prompts adopt --reason).'
67
+ + ' Una llave que adopta sola cambiaria lo que el agente lee en cada turno sin que nadie firme el cambio.',
68
+ adopt_latest: 'lo mismo que auto_adopt: la configuracion puede decir de donde mirar y cuando avisar, no adoptar.',
69
+ always_latest: 'lo mismo que auto_adopt. Si lo que queres es seguir al metodo sin congelar,'
70
+ + ' eso es prompts_source="published", y queda declarado en el proyecto.',
71
+ };
72
+ function esObjeto(v) {
73
+ return v != null && typeof v === 'object' && !Array.isArray(v);
74
+ }
75
+ function url(v, campo, problems) {
76
+ if (v === undefined)
77
+ return undefined;
78
+ if (typeof v !== 'string' || !/^https?:\/\/|^file:\/\//.test(v.trim())) {
79
+ problems.push('method.' + campo + ' tiene que ser una direccion http(s) o file: -- ignorada');
80
+ return undefined;
81
+ }
82
+ return v.trim();
83
+ }
84
+ /** Leer la seccion `method` del proyecto. Nunca lanza: un proyecto con un
85
+ * settings roto tiene que poder seguir corriendo con los defaults, y
86
+ * enterarse de que su archivo no se esta aplicando. */
87
+ export async function readMethodConfig(projectRoot) {
88
+ const cfg = defaultMethodConfig();
89
+ const problems = [];
90
+ const refused = [];
91
+ let raw;
92
+ try {
93
+ raw = JSON.parse(await fs.readFile(methodConfigPath(projectRoot), 'utf8'));
94
+ }
95
+ catch (e) {
96
+ const err = e;
97
+ if (err && err.code !== 'ENOENT') {
98
+ problems.push('no pude leer ' + METHOD_CONFIG_REL + ': ' + e.message
99
+ + ' -- el proyecto corre con la configuracion por omision del metodo');
100
+ }
101
+ return { cfg, problems, refused, present: false };
102
+ }
103
+ if (!esObjeto(raw)) {
104
+ problems.push(METHOD_CONFIG_REL + ' no es un objeto JSON -- ignorado');
105
+ return { cfg, problems, refused, present: true };
106
+ }
107
+ const m = raw['method'];
108
+ if (m === undefined)
109
+ return { cfg, problems, refused, present: true };
110
+ if (!esObjeto(m)) {
111
+ problems.push('method tiene que ser un objeto -- ignorado');
112
+ return { cfg, problems, refused, present: true };
113
+ }
114
+ for (const [k, motivo] of Object.entries(LLAVES_PROHIBIDAS)) {
115
+ if (m[k] !== undefined) {
116
+ refused.push('method.' + k + ' NO se aplica: ' + motivo);
117
+ }
118
+ }
119
+ if (m['prompts_source'] !== undefined) {
120
+ const v = m['prompts_source'];
121
+ if (typeof v === 'string' && PROMPTS_SOURCES.includes(v)) {
122
+ cfg.prompts_source = v;
123
+ }
124
+ else {
125
+ problems.push('method.prompts_source acepta ' + PROMPTS_SOURCES.join('|')
126
+ + ' -- se usa ' + cfg.prompts_source);
127
+ }
128
+ }
129
+ const pu = url(m['prompts_url'], 'prompts_url', problems);
130
+ if (pu)
131
+ cfg.prompts_url = pu;
132
+ const gu = url(m['gates_url'], 'gates_url', problems);
133
+ if (gu)
134
+ cfg.gates_url = gu;
135
+ const lu = url(m['ledger_url'], 'ledger_url', problems);
136
+ if (lu)
137
+ cfg.ledger_url = lu;
138
+ if (m['check_on_start'] !== undefined) {
139
+ if (typeof m['check_on_start'] === 'boolean')
140
+ cfg.check_on_start = m['check_on_start'];
141
+ else
142
+ problems.push('method.check_on_start tiene que ser booleano -- se usa el ajuste de la maquina');
143
+ }
144
+ if (m['strict'] !== undefined) {
145
+ if (typeof m['strict'] === 'boolean')
146
+ cfg.strict = m['strict'];
147
+ else
148
+ problems.push('method.strict tiene que ser booleano -- se usa ' + cfg.strict);
149
+ }
150
+ /* Las llaves que nadie reconoce se nombran. Un typo en una politica que
151
+ * decide como se mide un proyecto no puede pasar inadvertido. */
152
+ const conocidas = new Set([
153
+ 'prompts_source', 'prompts_url', 'gates_url', 'ledger_url', 'check_on_start', 'strict',
154
+ ...Object.keys(LLAVES_PROHIBIDAS),
155
+ ]);
156
+ for (const k of Object.keys(m)) {
157
+ if (!conocidas.has(k))
158
+ problems.push('method.' + k + ' no es una llave que Forge conozca -- ignorada');
159
+ }
160
+ return { cfg, problems, refused, present: true };
161
+ }
162
+ /** Resolver si este proyecto avisa de versiones nuevas: el proyecto manda,
163
+ * la maquina pone el default. */
164
+ export function updateCheckEnabled(cfg, machine) {
165
+ if (cfg.check_on_start !== undefined)
166
+ return cfg.check_on_start;
167
+ return machine !== 'off';
168
+ }
169
+ /**
170
+ * EL MODO ESTRICTO. Un proyecto que declara `method.strict` no corre la
171
+ * escalera leyendo el catalogo compilado ni los prompts vendorizados: eso
172
+ * es medir con un instrumento distinto del que el proyecto declaro, y para
173
+ * un equipo que esta midiendo es peor que no correr.
174
+ *
175
+ * Devuelve el veredicto en vez de lanzar: el que decide si frena es el
176
+ * llamador (el arranque frena; un `status` informa y sigue, porque negarle
177
+ * a alguien VER el estado por no haber congelado seria absurdo).
178
+ */
179
+ export function methodStrictVerdict(cfg, estado) {
180
+ const missing = [];
181
+ if (!estado.gates_frozen)
182
+ missing.push('las compuertas');
183
+ if (!estado.prompts_frozen)
184
+ missing.push('los prompts');
185
+ if (!cfg.strict) {
186
+ return {
187
+ strict: false, ok: true, missing,
188
+ detail: missing.length
189
+ ? 'sin congelar: ' + missing.join(' y ') + '. El proyecto NO declara modo estricto,'
190
+ + ' asi que corre leyendo lo que haya (catalogo compilado / prompts publicados) y lo dice.'
191
+ : 'las dos mitades estan congeladas.',
192
+ };
193
+ }
194
+ if (!missing.length) {
195
+ return { strict: true, ok: true, missing, detail: 'modo estricto: las dos mitades estan congeladas.' };
196
+ }
197
+ return {
198
+ strict: true, ok: false, missing,
199
+ detail: 'MODO ESTRICTO: este proyecto declara method.strict y le falta congelar ' + missing.join(' y ')
200
+ + '. No corro la escalera leyendo otra version del metodo que la que el proyecto declaro:'
201
+ + ' corre `yf urazuke freeze` (congela lo que lee hoy) o'
202
+ + ' `yf urazuke gates adopt --reason "..."` / `yf urazuke prompts adopt --reason "..."`'
203
+ + ' para adoptar la publicada. Si no queres esta compuerta, saca method.strict del'
204
+ + ' ' + METHOD_CONFIG_REL + '.',
205
+ };
206
+ }
207
+ /** Una linea por mitad que tenga version nueva publicada. Sin red, sin
208
+ * congelado o sin version publicada legible NO dice nada: un aviso que no
209
+ * pudo mirar no se informa como "estas al dia". */
210
+ export function compareVersions(half, frozen, published) {
211
+ if (!frozen || !published || frozen === published)
212
+ return undefined;
213
+ return {
214
+ half, frozen, published,
215
+ detail: (half === 'gates' ? 'las compuertas' : 'los prompts') + ' del proyecto estan congelados en '
216
+ + frozen + ' y el metodo publica ' + published + '. Adoptarla es una decision con razon escrita:'
217
+ + ' `yf urazuke ' + (half === 'gates' ? 'gates' : 'prompts') + ' pull` mide lo que cambia sin escribir nada.',
218
+ };
219
+ }
220
+ /**
221
+ * EL ESTADO DEL METODO EN ESTE PROYECTO, de una sola lectura: que dice la
222
+ * configuracion, que esta congelado, si el modo estricto deja arrancar y si
223
+ * hay version nueva publicada.
224
+ *
225
+ * `check_updates` sale de la maquina (limits.json urazuke.update_check) y lo
226
+ * pisa el proyecto. Cuando esta apagado NO se sale a la red, y el resultado
227
+ * lo dice en vez de informar silencio como si fuera "al dia".
228
+ */
229
+ export async function methodState(projectRoot, opts = {}) {
230
+ const { cfg, problems, refused } = await readMethodConfig(projectRoot);
231
+ const config_notices = [...refused, ...problems];
232
+ let gates_frozen = false;
233
+ let gates_version;
234
+ try {
235
+ const { readFrozenGates } = await import('./gates_data.js');
236
+ const g = await readFrozenGates(projectRoot);
237
+ if (g.gates) {
238
+ gates_frozen = true;
239
+ gates_version = g.gates.version;
240
+ }
241
+ else if (g.refused?.length)
242
+ config_notices.push('el congelado de compuertas NO verifica: ' + g.refused.join('; '));
243
+ }
244
+ catch { /* sin congelado */ }
245
+ let prompts_frozen = false;
246
+ let prompts_version;
247
+ try {
248
+ const { readFrozenPrompts, declaredPromptsVersion } = await import('./prompts_freeze.js');
249
+ const p = await readFrozenPrompts(projectRoot);
250
+ if (p.prompts) {
251
+ prompts_frozen = true;
252
+ prompts_version = declaredPromptsVersion(p.prompts);
253
+ }
254
+ else if (p.refused?.length)
255
+ config_notices.push('el congelado de prompts NO verifica: ' + p.refused.join('; '));
256
+ }
257
+ catch { /* sin congelado */ }
258
+ const strict = methodStrictVerdict(cfg, { gates_frozen, prompts_frozen });
259
+ const state = {
260
+ cfg, config_notices, gates_frozen, prompts_frozen, strict, updates: [],
261
+ ...(gates_version ? { gates_version } : {}),
262
+ ...(prompts_version ? { prompts_version } : {}),
263
+ };
264
+ if (!updateCheckEnabled(cfg, opts.machine_update_check)) {
265
+ state.could_not_check = 'el aviso de version nueva esta apagado'
266
+ + ' (limits.json urazuke.update_check=off, o method.check_on_start=false en el proyecto):'
267
+ + ' no mire, asi que no se si hay una version nueva.';
268
+ return state;
269
+ }
270
+ /* SIN CONGELADO NO HAY CON QUE COMPARAR, y eso NO es "estas al dia".
271
+ * Decirlo asi es la mitad del defecto que este modulo viene a cerrar: un
272
+ * proyecto sin congelar lee lo publicado en cada turno, asi que por
273
+ * construccion no tiene version nueva que adoptar -- y tampoco tiene
274
+ * version fija, que es la otra mitad de la frase y la que importa. */
275
+ if (!prompts_frozen) {
276
+ state.could_not_check = 'los prompts de este proyecto NO estan congelados, asi que no hay con que'
277
+ + ' comparar: lee lo publicado en cada turno. No es "al dia": es "sin version fija".'
278
+ + ' `yf urazuke freeze` congela lo que lee hoy.';
279
+ return state;
280
+ }
281
+ /* Los prompts son la mitad que se puede comparar sin instalar nada: la
282
+ * definicion de compuertas en vigor NO sale a la red por diseno, asi que
283
+ * su contraste es `yf urazuke gates pull`, que es un acto explicito. */
284
+ try {
285
+ const { loadPublishedPrompts } = await import('./prompts_client.js');
286
+ const pub = await loadPublishedPrompts({
287
+ ...(opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}),
288
+ ...(opts.offline ? { offline: true } : {}),
289
+ ...(cfg.prompts_url ? { url: cfg.prompts_url } : {}),
290
+ });
291
+ if (!pub) {
292
+ state.could_not_check = 'no pude leer los prompts publicados (sin red y sin cache util):'
293
+ + ' no se si hay una version nueva, que no es lo mismo que estar al dia.';
294
+ }
295
+ else {
296
+ const { declaredPromptsVersion } = await import('./prompts_freeze.js');
297
+ const publicada = declaredPromptsVersion(pub.payload);
298
+ const n = compareVersions('prompts', prompts_version, publicada);
299
+ if (n)
300
+ state.updates.push(n);
301
+ }
302
+ }
303
+ catch (e) {
304
+ state.could_not_check = 'no pude comparar contra lo publicado: ' + e.message;
305
+ }
306
+ return state;
307
+ }
308
+ /** El estado en lineas, para el CLI y el arranque. */
309
+ export function renderMethodState(s) {
310
+ const L = [];
311
+ L.push('compuertas: ' + (s.gates_frozen ? 'congeladas en ' + s.gates_version : 'SIN congelar')
312
+ + ' | prompts: ' + (s.prompts_frozen ? 'congelados en ' + s.prompts_version : 'SIN congelar'));
313
+ L.push('fuente de los prompts: ' + s.cfg.prompts_source
314
+ + (s.cfg.prompts_url ? ' (' + s.cfg.prompts_url + ')' : '')
315
+ + ' | modo estricto: ' + (s.cfg.strict ? 'SI' : 'no'));
316
+ for (const n of s.config_notices)
317
+ L.push('aviso: ' + n);
318
+ if (!s.strict.ok)
319
+ L.push(s.strict.detail);
320
+ for (const u of s.updates)
321
+ L.push('VERSION NUEVA: ' + u.detail);
322
+ if (s.could_not_check)
323
+ L.push('aviso: ' + s.could_not_check);
324
+ if (!s.updates.length && !s.could_not_check)
325
+ L.push('no hay version nueva publicada de los prompts.');
326
+ return L;
327
+ }
328
+ //# sourceMappingURL=method_config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"method_config.js","sourceRoot":"","sources":["../../src/urazuke/method_config.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  export declare const DEFAULT_PROMPTS_URL = "https://yujin.app/urazuke/api/prompts.json";
2
- export type PromptSource = 'override' | 'remote' | 'cache' | 'vendored';
2
+ export type PromptSource = 'override' | 'frozen' | 'remote' | 'cache' | 'vendored';
3
3
  export interface PromptsApiPayload {
4
4
  version: string;
5
5
  generated_at?: string;
@@ -15,6 +15,19 @@ export interface ResolvedPrompts {
15
15
  version: string;
16
16
  /** Keys the project overrides. */
17
17
  overridden: string[];
18
+ /** El congelado del proyecto, cuando hay uno que verifica. */
19
+ frozen?: {
20
+ version: string;
21
+ hash: string;
22
+ frozen_at?: string;
23
+ frozen_reason?: string;
24
+ };
25
+ /** Lo que el dueno tiene que saber y nadie mas le va a decir: un
26
+ * congelado que no verifica, un archivo viejo que no declara si es
27
+ * congelado u override, una llave de configuracion rechazada. Nunca se
28
+ * calla: un congelado que se ignora en silencio es la version que el
29
+ * proyecto creia tener y no tiene. */
30
+ notices?: string[];
18
31
  }
19
32
  export interface PromptOverridesFile {
20
33
  version: 1;
@@ -55,7 +68,16 @@ export declare function resolveCanonicalPrompts(opts?: FetchOptions): Promise<{
55
68
  source: Record<string, PromptSource>;
56
69
  version: string;
57
70
  }>;
58
- /** Effective prompts for a project: overrides > published > vendored. */
71
+ /**
72
+ * Effective prompts for a project: overrides > FROZEN > published > vendored.
73
+ *
74
+ * El congelado entra en el medio y cambia una cosa mas que el orden: cuando
75
+ * hay un congelado que verifica y la configuracion del proyecto no pide otra
76
+ * cosa, esta funcion NO SALE A LA RED. Es la misma regla que las compuertas
77
+ * ya cumplen (resolveGates no consulta el portal nunca): un proyecto no
78
+ * cambia de regla entre dos turnos, y resolver un prompt no es el momento de
79
+ * descubrir que el portal se movio.
80
+ */
59
81
  export declare function resolvePrompts(projectRoot: string | undefined, opts?: FetchOptions): Promise<ResolvedPrompts>;
60
82
  export interface PullResult {
61
83
  /** The canonical version these prompts were pulled from. */
@@ -66,16 +88,24 @@ export interface PullResult {
66
88
  * before (a fresh `pull` of an up-to-date project reports none). */
67
89
  changed: string[];
68
90
  }
69
- /** Bring the CANONICAL prompts (never this project's own overrides, even
70
- * if some exist already) and write them into
71
- * `<root>/.forge/urazuke-prompts.json`, replacing one contract (`key`) or
72
- * every contract Forge knows about. Unlike `reset` -- which deletes the
73
- * override and falls back to live resolution -- `pull` leaves an explicit,
74
- * on-disk copy the project keeps control of afterwards (D-036): it does
75
- * not depend on the network or on which Forge version is installed to
76
- * know what text the agent is working from, and the owner can still edit
77
- * it by hand (or with `prompts set`) once pulled. */
78
- export declare function pullPrompts(projectRoot: string, opts?: FetchOptions & {
91
+ /**
92
+ * Copiar los prompts CANONICOS al archivo de OVERRIDES del proyecto,
93
+ * pisando lo que hubiera.
94
+ *
95
+ * SE LLAMABA `pullPrompts`, Y ESE NOMBRE ERA EL DEFECTO (PND-277). En el
96
+ * mismo comando padre, `gates pull` MIDE y no escribe; este ESCRIBIA y no
97
+ * media. Un dueno que aprendio el seguro y corrio el otro por analogia ya
98
+ * se habia pisado los prompts del proyecto. El nombre prometia el
99
+ * comportamiento del otro, que es peor que no existir.
100
+ *
101
+ * La capacidad sigue siendo legitima para UN caso -- "quiero el texto
102
+ * publicado como punto de partida para editarlo a mano" -- asi que no se
103
+ * borro: se le puso el nombre que dice lo que hace, y el CLI la expone como
104
+ * `yf urazuke prompts copy-to-overrides`. Lo que escribe son OVERRIDES del
105
+ * dueno, no un congelado: el congelado tiene version, huella y razon, y se
106
+ * escribe con `prompts adopt --reason` (src/urazuke/prompts_freeze.ts).
107
+ */
108
+ export declare function copyCanonicalIntoOverrides(projectRoot: string, opts?: FetchOptions & {
79
109
  key?: string;
80
110
  }): Promise<PullResult>;
81
111
  //# sourceMappingURL=prompts_client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts_client.d.ts","sourceRoot":"","sources":["../../src/urazuke/prompts_client.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,mBAAmB,+CAA+C,CAAC;AAIhF,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAC3C,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACrC,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,CAAC,CAAC;IACX,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAcD,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAYD,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAYrF;AAED,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlG;AAgBD,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;qEAIiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;wDACwD;AACxD,wBAAsB,oBAAoB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAA;CAAE,GAAG,SAAS,CAAC,CAuBnJ;AAED;;;;uCAIuC;AACvC,wBAAsB,uBAAuB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAarL;AAED,yEAAyE;AACzE,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAUvH;AAED,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;yEACqE;IACrE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;sDAQsD;AACtD,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,YAAY,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CActH"}
1
+ {"version":3,"file":"prompts_client.d.ts","sourceRoot":"","sources":["../../src/urazuke/prompts_client.ts"],"names":[],"mappings":"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"}
@@ -3,10 +3,18 @@
3
3
  *
4
4
  * 1. The project's overrides: <root>/.forge/urazuke-prompts.json
5
5
  * (the owner controls the text; `yf urazuke prompts set|reset`).
6
- * 2. The method's published API: https://yujin.app/urazuke/api/prompts.json
6
+ * 2. THE PROJECT'S FROZEN COPY: <root>/.forge/urazuke-prompts-frozen.json
7
+ * (PND-277, 2026-11-03). The version of the method this project lives
8
+ * on, sealed and with the owner's written reason inside. It sits
9
+ * BETWEEN the overrides and the published file on purpose: it pins the
10
+ * version without taking the text away from the owner, which is the
11
+ * reason the overrides exist. And a frozen project does NOT go to the
12
+ * network to resolve a prompt -- same rule the gates already follow:
13
+ * a project does not change rule between two turns.
14
+ * 3. The method's published API: https://yujin.app/urazuke/api/prompts.json
7
15
  * (cached at ~/.yujin-forge/cache/urazuke_prompts.json, 24 h fresh,
8
16
  * 30 days stale-on-failure).
9
- * 3. The vendored copy in prompts.generated.ts (offline fallback).
17
+ * 4. The vendored copy in prompts.generated.ts (offline fallback).
10
18
  *
11
19
  * Why the API and not only the vendored copy: the method evolves in its own
12
20
  * repository and publishes in eight languages; Forge should follow the
@@ -134,7 +142,13 @@ export async function resolveCanonicalPrompts(opts = {}) {
134
142
  let version = URAZUKE_PROMPTS_SOURCE;
135
143
  const pub = await loadPublishedPrompts(opts);
136
144
  if (pub) {
137
- version = 'pkuschnirof/urazuke@' + pub.payload.version;
145
+ /* La identidad de lo publicado es corpus_version, no el sha: el propio
146
+ * payload lo dice ("ninguna comparacion mira esto") y el registro
147
+ * append-only anota por corpus_version. Forge venia sellando cada
148
+ * recibo con el sha -- que, ademas, nombra el cambio ANTERIOR al que
149
+ * contiene el archivo. Fallback al sha para un payload viejo. */
150
+ const declarada = pub.payload['corpus_version'];
151
+ version = 'pkuschnirof/urazuke@' + (typeof declarada === 'string' && declarada.trim() ? declarada : pub.payload.version);
138
152
  for (const [k, v] of Object.entries(pub.payload.contracts)) {
139
153
  if (v.length) {
140
154
  prompts[k] = v;
@@ -144,9 +158,77 @@ export async function resolveCanonicalPrompts(opts = {}) {
144
158
  }
145
159
  return { prompts, source, version };
146
160
  }
147
- /** Effective prompts for a project: overrides > published > vendored. */
161
+ /**
162
+ * Effective prompts for a project: overrides > FROZEN > published > vendored.
163
+ *
164
+ * El congelado entra en el medio y cambia una cosa mas que el orden: cuando
165
+ * hay un congelado que verifica y la configuracion del proyecto no pide otra
166
+ * cosa, esta funcion NO SALE A LA RED. Es la misma regla que las compuertas
167
+ * ya cumplen (resolveGates no consulta el portal nunca): un proyecto no
168
+ * cambia de regla entre dos turnos, y resolver un prompt no es el momento de
169
+ * descubrir que el portal se movio.
170
+ */
148
171
  export async function resolvePrompts(projectRoot, opts = {}) {
149
- const { prompts, source, version } = await resolveCanonicalPrompts(opts);
172
+ const notices = [];
173
+ let frozen;
174
+ let frozenContracts;
175
+ let fuente = 'frozen';
176
+ if (projectRoot) {
177
+ try {
178
+ const { readMethodConfig } = await import('./method_config.js');
179
+ const cfg = await readMethodConfig(projectRoot);
180
+ fuente = cfg.cfg.prompts_source;
181
+ for (const r of cfg.refused)
182
+ notices.push(r);
183
+ for (const p of cfg.problems)
184
+ notices.push(p);
185
+ if (cfg.cfg.prompts_url && !opts.url)
186
+ opts = { ...opts, url: cfg.cfg.prompts_url };
187
+ }
188
+ catch { /* sin configuracion legible, el default: congelado primero */ }
189
+ if (fuente === 'frozen') {
190
+ try {
191
+ const { readFrozenPrompts, declaredPromptsVersion } = await import('./prompts_freeze.js');
192
+ const fr = await readFrozenPrompts(projectRoot);
193
+ if (fr.prompts) {
194
+ frozenContracts = fr.prompts.contracts;
195
+ const meta = fr.prompts;
196
+ frozen = {
197
+ version: declaredPromptsVersion(fr.prompts),
198
+ hash: fr.prompts.content_hash.value,
199
+ ...(typeof meta['frozen_at'] === 'string' ? { frozen_at: meta['frozen_at'] } : {}),
200
+ ...(typeof meta['frozen_reason'] === 'string' ? { frozen_reason: meta['frozen_reason'] } : {}),
201
+ };
202
+ }
203
+ else if (fr.refused?.length) {
204
+ /* Un congelado que no verifica NO se usa y NO se calla: el
205
+ * proyecto pasa a leer lo publicado, que es otra version que la
206
+ * que creia haber fijado. */
207
+ notices.push('el congelado de prompts de este proyecto NO verifica y no lo estoy usando: '
208
+ + fr.refused.join('; ') + '. Mientras siga asi, el proyecto lee los prompts publicados'
209
+ + ' y NO la version que creia haber congelado. Restauralo desde el repositorio o borralo'
210
+ + ' para que el proximo freeze lo vuelva a escribir.');
211
+ }
212
+ }
213
+ catch { /* el congelado es opcional */ }
214
+ }
215
+ }
216
+ /* Con congelado no hace falta la red; sin congelado, lo publicado (o la
217
+ * copia vendorizada si la configuracion lo pide). */
218
+ const canonOpts = frozenContracts || fuente === 'vendored'
219
+ ? { ...opts, offline: true }
220
+ : opts;
221
+ const { prompts, source, version: versionPublicada } = await resolveCanonicalPrompts(canonOpts);
222
+ let version = versionPublicada;
223
+ if (frozenContracts && frozen) {
224
+ for (const [k, v] of Object.entries(frozenContracts)) {
225
+ if (v.length) {
226
+ prompts[k] = v;
227
+ source[k] = 'frozen';
228
+ }
229
+ }
230
+ version = 'pkuschnirof/urazuke@' + frozen.version;
231
+ }
150
232
  const overridden = [];
151
233
  if (projectRoot) {
152
234
  const ov = await readOverrides(projectRoot);
@@ -155,19 +237,41 @@ export async function resolvePrompts(projectRoot, opts = {}) {
155
237
  source[k] = 'override';
156
238
  overridden.push(k);
157
239
  }
240
+ if (overridden.length && !frozen) {
241
+ /* EL ARCHIVO AMBIGUO (el caso del brazo C1): un
242
+ * .forge/urazuke-prompts.json escrito por el pull viejo es
243
+ * indistinguible de una edicion a mano. No se adivina: se dice. */
244
+ notices.push('este proyecto tiene ' + overridden.length + ' contrato(s) en'
245
+ + ' .forge/urazuke-prompts.json y NINGUN congelado declarado. Ese archivo no dice si es'
246
+ + ' una copia congelada o una edicion a mano, y no lo adivino:'
247
+ + ' `yf urazuke prompts pull` lo mide y `yf urazuke prompts adopt --reason "..."`'
248
+ + ' lo convierte en un congelado con autor.');
249
+ }
158
250
  }
159
- return { prompts, source, version, overridden: overridden.sort() };
251
+ return {
252
+ prompts, source, version, overridden: overridden.sort(),
253
+ ...(frozen ? { frozen } : {}),
254
+ ...(notices.length ? { notices } : {}),
255
+ };
160
256
  }
161
- /** Bring the CANONICAL prompts (never this project's own overrides, even
162
- * if some exist already) and write them into
163
- * `<root>/.forge/urazuke-prompts.json`, replacing one contract (`key`) or
164
- * every contract Forge knows about. Unlike `reset` -- which deletes the
165
- * override and falls back to live resolution -- `pull` leaves an explicit,
166
- * on-disk copy the project keeps control of afterwards (D-036): it does
167
- * not depend on the network or on which Forge version is installed to
168
- * know what text the agent is working from, and the owner can still edit
169
- * it by hand (or with `prompts set`) once pulled. */
170
- export async function pullPrompts(projectRoot, opts = {}) {
257
+ /**
258
+ * Copiar los prompts CANONICOS al archivo de OVERRIDES del proyecto,
259
+ * pisando lo que hubiera.
260
+ *
261
+ * SE LLAMABA `pullPrompts`, Y ESE NOMBRE ERA EL DEFECTO (PND-277). En el
262
+ * mismo comando padre, `gates pull` MIDE y no escribe; este ESCRIBIA y no
263
+ * media. Un dueno que aprendio el seguro y corrio el otro por analogia ya
264
+ * se habia pisado los prompts del proyecto. El nombre prometia el
265
+ * comportamiento del otro, que es peor que no existir.
266
+ *
267
+ * La capacidad sigue siendo legitima para UN caso -- "quiero el texto
268
+ * publicado como punto de partida para editarlo a mano" -- asi que no se
269
+ * borro: se le puso el nombre que dice lo que hace, y el CLI la expone como
270
+ * `yf urazuke prompts copy-to-overrides`. Lo que escribe son OVERRIDES del
271
+ * dueno, no un congelado: el congelado tiene version, huella y razon, y se
272
+ * escribe con `prompts adopt --reason` (src/urazuke/prompts_freeze.ts).
273
+ */
274
+ export async function copyCanonicalIntoOverrides(projectRoot, opts = {}) {
171
275
  const canonical = await resolveCanonicalPrompts(opts);
172
276
  if (opts.key && !canonical.prompts[opts.key])
173
277
  throw new Error('no existe el contrato ' + opts.key);