@nac3/forge-cli 0.2.1-alpha.60 → 1.0.1

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 (303) hide show
  1. package/README.md +5 -1
  2. package/dist/agents/bridge.d.ts.map +1 -1
  3. package/dist/agents/bridge.js +27 -0
  4. package/dist/agents/bridge.js.map +1 -1
  5. package/dist/agents/config_resolver.d.ts.map +1 -1
  6. package/dist/agents/config_resolver.js +15 -15
  7. package/dist/agents/config_resolver.js.map +1 -1
  8. package/dist/agents/runner.d.ts +8 -0
  9. package/dist/agents/runner.d.ts.map +1 -1
  10. package/dist/agents/runner.js +58 -11
  11. package/dist/agents/runner.js.map +1 -1
  12. package/dist/agents/system_prompt.d.ts.map +1 -1
  13. package/dist/agents/system_prompt.js +2 -1
  14. package/dist/agents/system_prompt.js.map +1 -1
  15. package/dist/bin/yf.d.ts.map +1 -1
  16. package/dist/bin/yf.js +18 -0
  17. package/dist/bin/yf.js.map +1 -1
  18. package/dist/chat/claude.d.ts +13 -0
  19. package/dist/chat/claude.d.ts.map +1 -1
  20. package/dist/chat/claude.js +95 -10
  21. package/dist/chat/claude.js.map +1 -1
  22. package/dist/chat/claude_cli.d.ts +10 -0
  23. package/dist/chat/claude_cli.d.ts.map +1 -1
  24. package/dist/chat/claude_cli.js +97 -16
  25. package/dist/chat/claude_cli.js.map +1 -1
  26. package/dist/chat/completion_hallucination_detector.d.ts +11 -0
  27. package/dist/chat/completion_hallucination_detector.d.ts.map +1 -1
  28. package/dist/chat/completion_hallucination_detector.js +37 -2
  29. package/dist/chat/completion_hallucination_detector.js.map +1 -1
  30. package/dist/chat/doctrine_digest.d.ts.map +1 -1
  31. package/dist/chat/doctrine_digest.js +10 -6
  32. package/dist/chat/doctrine_digest.js.map +1 -1
  33. package/dist/chat/panel.d.ts.map +1 -1
  34. package/dist/chat/panel.js +923 -50
  35. package/dist/chat/panel.js.map +1 -1
  36. package/dist/chat/refusal_detector.d.ts.map +1 -1
  37. package/dist/chat/refusal_detector.js +2 -1
  38. package/dist/chat/refusal_detector.js.map +1 -1
  39. package/dist/chat/server.d.ts +1 -0
  40. package/dist/chat/server.d.ts.map +1 -1
  41. package/dist/chat/server.js +960 -73
  42. package/dist/chat/server.js.map +1 -1
  43. package/dist/chat/session_projects.d.ts +31 -0
  44. package/dist/chat/session_projects.d.ts.map +1 -0
  45. package/dist/chat/session_projects.js +36 -0
  46. package/dist/chat/session_projects.js.map +1 -0
  47. package/dist/chat/session_store.d.ts +32 -0
  48. package/dist/chat/session_store.d.ts.map +1 -0
  49. package/dist/chat/session_store.js +58 -0
  50. package/dist/chat/session_store.js.map +1 -0
  51. package/dist/chat/tooling_section.d.ts +11 -0
  52. package/dist/chat/tooling_section.d.ts.map +1 -0
  53. package/dist/chat/tooling_section.js +70 -0
  54. package/dist/chat/tooling_section.js.map +1 -0
  55. package/dist/chat/tools/app_backend_dispatch.d.ts.map +1 -1
  56. package/dist/chat/tools/app_backend_dispatch.js +44 -1
  57. package/dist/chat/tools/app_backend_dispatch.js.map +1 -1
  58. package/dist/chat/tools/fs_editor.d.ts.map +1 -1
  59. package/dist/chat/tools/fs_editor.js +53 -3
  60. package/dist/chat/tools/fs_editor.js.map +1 -1
  61. package/dist/chat/tools/graph.js +2 -2
  62. package/dist/chat/tools/graph.js.map +1 -1
  63. package/dist/chat/tools/keys.d.ts.map +1 -1
  64. package/dist/chat/tools/keys.js +5 -18
  65. package/dist/chat/tools/keys.js.map +1 -1
  66. package/dist/chat/tools/nac3_invoke.d.ts.map +1 -1
  67. package/dist/chat/tools/nac3_invoke.js +16 -7
  68. package/dist/chat/tools/nac3_invoke.js.map +1 -1
  69. package/dist/chat/tools/shell.d.ts +6 -0
  70. package/dist/chat/tools/shell.d.ts.map +1 -1
  71. package/dist/chat/tools/shell.js +39 -0
  72. package/dist/chat/tools/shell.js.map +1 -1
  73. package/dist/chat/tools/workflow.d.ts +20 -0
  74. package/dist/chat/tools/workflow.d.ts.map +1 -1
  75. package/dist/chat/tools/workflow.js +98 -0
  76. package/dist/chat/tools/workflow.js.map +1 -1
  77. package/dist/chat/tools.d.ts.map +1 -1
  78. package/dist/chat/tools.js +79 -1
  79. package/dist/chat/tools.js.map +1 -1
  80. package/dist/chat/turn_control.d.ts +42 -0
  81. package/dist/chat/turn_control.d.ts.map +1 -0
  82. package/dist/chat/turn_control.js +53 -0
  83. package/dist/chat/turn_control.js.map +1 -0
  84. package/dist/commands/brain.js +1 -1
  85. package/dist/commands/chat.d.ts.map +1 -1
  86. package/dist/commands/chat.js +61 -10
  87. package/dist/commands/chat.js.map +1 -1
  88. package/dist/commands/graph.js +9 -9
  89. package/dist/commands/graph.js.map +1 -1
  90. package/dist/commands/keys_setup.d.ts +10 -28
  91. package/dist/commands/keys_setup.d.ts.map +1 -1
  92. package/dist/commands/keys_setup.js +54 -228
  93. package/dist/commands/keys_setup.js.map +1 -1
  94. package/dist/commands/license.d.ts.map +1 -1
  95. package/dist/commands/license.js +52 -28
  96. package/dist/commands/license.js.map +1 -1
  97. package/dist/commands/mcp.d.ts.map +1 -1
  98. package/dist/commands/mcp.js +62 -6
  99. package/dist/commands/mcp.js.map +1 -1
  100. package/dist/commands/mobile.d.ts +1 -1
  101. package/dist/commands/mobile.d.ts.map +1 -1
  102. package/dist/commands/mobile.js +32 -28
  103. package/dist/commands/mobile.js.map +1 -1
  104. package/dist/commands/onboard.d.ts +19 -0
  105. package/dist/commands/onboard.d.ts.map +1 -0
  106. package/dist/commands/onboard.js +126 -0
  107. package/dist/commands/onboard.js.map +1 -0
  108. package/dist/commands/pending.d.ts.map +1 -1
  109. package/dist/commands/pending.js +25 -1
  110. package/dist/commands/pending.js.map +1 -1
  111. package/dist/commands/projects.js +25 -1
  112. package/dist/commands/projects.js.map +1 -1
  113. package/dist/commands/review-screens.js +28 -1
  114. package/dist/commands/review-screens.js.map +1 -1
  115. package/dist/commands/workflow.d.ts +18 -0
  116. package/dist/commands/workflow.d.ts.map +1 -0
  117. package/dist/commands/workflow.js +253 -0
  118. package/dist/commands/workflow.js.map +1 -0
  119. package/dist/core/brain_config.d.ts +2 -0
  120. package/dist/core/brain_config.d.ts.map +1 -1
  121. package/dist/core/brain_config.js +18 -3
  122. package/dist/core/brain_config.js.map +1 -1
  123. package/dist/core/cf_tunnel.d.ts.map +1 -1
  124. package/dist/core/cf_tunnel.js +8 -2
  125. package/dist/core/cf_tunnel.js.map +1 -1
  126. package/dist/core/cost_router.d.ts.map +1 -1
  127. package/dist/core/cost_router.js +11 -2
  128. package/dist/core/cost_router.js.map +1 -1
  129. package/dist/core/desktop_open.d.ts +16 -0
  130. package/dist/core/desktop_open.d.ts.map +1 -0
  131. package/dist/core/desktop_open.js +114 -0
  132. package/dist/core/desktop_open.js.map +1 -0
  133. package/dist/core/keys_envelope.d.ts.map +1 -1
  134. package/dist/core/keys_envelope.js +5 -1
  135. package/dist/core/keys_envelope.js.map +1 -1
  136. package/dist/core/limits_config.d.ts +5 -0
  137. package/dist/core/limits_config.d.ts.map +1 -1
  138. package/dist/core/limits_config.js +5 -0
  139. package/dist/core/limits_config.js.map +1 -1
  140. package/dist/core/logger.d.ts.map +1 -1
  141. package/dist/core/logger.js +3 -0
  142. package/dist/core/logger.js.map +1 -1
  143. package/dist/core/pairing.d.ts +6 -0
  144. package/dist/core/pairing.d.ts.map +1 -1
  145. package/dist/core/pairing.js +41 -2
  146. package/dist/core/pairing.js.map +1 -1
  147. package/dist/core/provider_keys.d.ts.map +1 -1
  148. package/dist/core/provider_keys.js +25 -12
  149. package/dist/core/provider_keys.js.map +1 -1
  150. package/dist/core/provider_models.js +1 -1
  151. package/dist/deploy/cloudflare.d.ts.map +1 -1
  152. package/dist/deploy/cloudflare.js +13 -2
  153. package/dist/deploy/cloudflare.js.map +1 -1
  154. package/dist/design/yujin_design_resolver.d.ts +16 -0
  155. package/dist/design/yujin_design_resolver.d.ts.map +1 -1
  156. package/dist/design/yujin_design_resolver.js +103 -20
  157. package/dist/design/yujin_design_resolver.js.map +1 -1
  158. package/dist/docs/doctrine/default-design-system.md +32 -0
  159. package/dist/docs/doctrine/office-tools.md +20 -0
  160. package/dist/docs/doctrine/pizarron.md +40 -0
  161. package/dist/docs/doctrine/verb-composition.md +16 -0
  162. package/dist/docs/doctrine/workflow-kinds.md +39 -22
  163. package/dist/docs/doctrine/workflow.md +12 -4
  164. package/dist/license/auto_sync.d.ts +22 -0
  165. package/dist/license/auto_sync.d.ts.map +1 -0
  166. package/dist/license/auto_sync.js +91 -0
  167. package/dist/license/auto_sync.js.map +1 -0
  168. package/dist/license/handle_key.d.ts +32 -0
  169. package/dist/license/handle_key.d.ts.map +1 -0
  170. package/dist/license/handle_key.js +56 -0
  171. package/dist/license/handle_key.js.map +1 -0
  172. package/dist/license/hito4_client.d.ts.map +1 -1
  173. package/dist/license/hito4_client.js +63 -25
  174. package/dist/license/hito4_client.js.map +1 -1
  175. package/dist/llm/gemini_client.d.ts.map +1 -1
  176. package/dist/llm/gemini_client.js +5 -2
  177. package/dist/llm/gemini_client.js.map +1 -1
  178. package/dist/llm/managed_client.d.ts.map +1 -1
  179. package/dist/llm/managed_client.js +14 -9
  180. package/dist/llm/managed_client.js.map +1 -1
  181. package/dist/mcp/plan_bridges.d.ts +17 -0
  182. package/dist/mcp/plan_bridges.d.ts.map +1 -0
  183. package/dist/mcp/plan_bridges.js +119 -0
  184. package/dist/mcp/plan_bridges.js.map +1 -0
  185. package/dist/migrate/ai-apply.d.ts.map +1 -1
  186. package/dist/migrate/ai-apply.js +25 -2
  187. package/dist/migrate/ai-apply.js.map +1 -1
  188. package/dist/nac3/internal_manifest.d.ts.map +1 -1
  189. package/dist/nac3/internal_manifest.js +200 -10
  190. package/dist/nac3/internal_manifest.js.map +1 -1
  191. package/dist/nac3/verb_tier_map.d.ts.map +1 -1
  192. package/dist/nac3/verb_tier_map.js +3 -0
  193. package/dist/nac3/verb_tier_map.js.map +1 -1
  194. package/dist/onboarding/concierge_client.d.ts +34 -0
  195. package/dist/onboarding/concierge_client.d.ts.map +1 -0
  196. package/dist/onboarding/concierge_client.js +80 -0
  197. package/dist/onboarding/concierge_client.js.map +1 -0
  198. package/dist/onboarding/next_step.d.ts +32 -0
  199. package/dist/onboarding/next_step.d.ts.map +1 -0
  200. package/dist/onboarding/next_step.js +60 -0
  201. package/dist/onboarding/next_step.js.map +1 -0
  202. package/dist/pending/store.d.ts +7 -0
  203. package/dist/pending/store.d.ts.map +1 -1
  204. package/dist/pending/store.js +19 -0
  205. package/dist/pending/store.js.map +1 -1
  206. package/dist/pending/types.d.ts +20 -0
  207. package/dist/pending/types.d.ts.map +1 -1
  208. package/dist/pending/types.js.map +1 -1
  209. package/dist/reader/parsers/epub.d.ts.map +1 -1
  210. package/dist/reader/parsers/epub.js +6 -1
  211. package/dist/reader/parsers/epub.js.map +1 -1
  212. package/dist/relay/board_snapshot.d.ts +69 -0
  213. package/dist/relay/board_snapshot.d.ts.map +1 -0
  214. package/dist/relay/board_snapshot.js +149 -0
  215. package/dist/relay/board_snapshot.js.map +1 -0
  216. package/dist/relay/command_consumer.d.ts +97 -0
  217. package/dist/relay/command_consumer.d.ts.map +1 -0
  218. package/dist/relay/command_consumer.js +135 -0
  219. package/dist/relay/command_consumer.js.map +1 -0
  220. package/dist/relay/mock_relay.d.ts +34 -0
  221. package/dist/relay/mock_relay.d.ts.map +1 -0
  222. package/dist/relay/mock_relay.js +93 -0
  223. package/dist/relay/mock_relay.js.map +1 -0
  224. package/dist/relay/relay_client.d.ts +28 -0
  225. package/dist/relay/relay_client.d.ts.map +1 -0
  226. package/dist/relay/relay_client.js +80 -0
  227. package/dist/relay/relay_client.js.map +1 -0
  228. package/dist/relay/relay_publisher.d.ts +59 -0
  229. package/dist/relay/relay_publisher.d.ts.map +1 -0
  230. package/dist/relay/relay_publisher.js +101 -0
  231. package/dist/relay/relay_publisher.js.map +1 -0
  232. package/dist/relay/types.d.ts +54 -0
  233. package/dist/relay/types.d.ts.map +1 -0
  234. package/dist/relay/types.js +8 -0
  235. package/dist/relay/types.js.map +1 -0
  236. package/dist/semantic_graph/ast_extract.d.ts +5 -0
  237. package/dist/semantic_graph/ast_extract.d.ts.map +1 -1
  238. package/dist/semantic_graph/ast_extract.js +46 -0
  239. package/dist/semantic_graph/ast_extract.js.map +1 -1
  240. package/dist/semantic_graph/derive.d.ts +12 -0
  241. package/dist/semantic_graph/derive.d.ts.map +1 -1
  242. package/dist/semantic_graph/derive.js +325 -6
  243. package/dist/semantic_graph/derive.js.map +1 -1
  244. package/dist/semantic_graph/store.d.ts +9 -0
  245. package/dist/semantic_graph/store.d.ts.map +1 -1
  246. package/dist/semantic_graph/store.js +23 -1
  247. package/dist/semantic_graph/store.js.map +1 -1
  248. package/dist/semantic_graph/types.d.ts +1 -1
  249. package/dist/semantic_graph/types.d.ts.map +1 -1
  250. package/dist/support/github_dispatcher.d.ts.map +1 -1
  251. package/dist/support/github_dispatcher.js +30 -2
  252. package/dist/support/github_dispatcher.js.map +1 -1
  253. package/dist/tasks/supervisor.d.ts +88 -0
  254. package/dist/tasks/supervisor.d.ts.map +1 -0
  255. package/dist/tasks/supervisor.js +308 -0
  256. package/dist/tasks/supervisor.js.map +1 -0
  257. package/dist/tasks/task_type.d.ts +11 -0
  258. package/dist/tasks/task_type.d.ts.map +1 -0
  259. package/dist/tasks/task_type.js +21 -0
  260. package/dist/tasks/task_type.js.map +1 -0
  261. package/dist/vault/store.d.ts.map +1 -1
  262. package/dist/vault/store.js +6 -1
  263. package/dist/vault/store.js.map +1 -1
  264. package/dist/version.d.ts +3 -5
  265. package/dist/version.d.ts.map +1 -1
  266. package/dist/version.js +3 -5
  267. package/dist/version.js.map +1 -1
  268. package/dist/voice/providers/google.d.ts.map +1 -1
  269. package/dist/voice/providers/google.js +6 -4
  270. package/dist/voice/providers/google.js.map +1 -1
  271. package/dist/workflow/config.d.ts +43 -0
  272. package/dist/workflow/config.d.ts.map +1 -0
  273. package/dist/workflow/config.js +199 -0
  274. package/dist/workflow/config.js.map +1 -0
  275. package/dist/workflow/instances.d.ts +40 -0
  276. package/dist/workflow/instances.d.ts.map +1 -0
  277. package/dist/workflow/instances.js +122 -0
  278. package/dist/workflow/instances.js.map +1 -0
  279. package/dist/workflow/multi_view.d.ts +27 -0
  280. package/dist/workflow/multi_view.d.ts.map +1 -0
  281. package/dist/workflow/multi_view.js +76 -0
  282. package/dist/workflow/multi_view.js.map +1 -0
  283. package/dist/workflow/orchestrator.d.ts +111 -0
  284. package/dist/workflow/orchestrator.d.ts.map +1 -0
  285. package/dist/workflow/orchestrator.js +241 -0
  286. package/dist/workflow/orchestrator.js.map +1 -0
  287. package/docs/doctrine/default-design-system.md +32 -0
  288. package/docs/doctrine/office-tools.md +20 -0
  289. package/docs/doctrine/pizarron.md +40 -0
  290. package/docs/doctrine/verb-composition.md +16 -0
  291. package/docs/doctrine/workflow-kinds.md +39 -22
  292. package/docs/doctrine/workflow.md +12 -4
  293. package/package.json +2 -1
  294. package/src/i18n/catalogs/ar.json +223 -210
  295. package/src/i18n/catalogs/de.json +223 -210
  296. package/src/i18n/catalogs/en.json +223 -210
  297. package/src/i18n/catalogs/es.json +223 -210
  298. package/src/i18n/catalogs/fr.json +223 -210
  299. package/src/i18n/catalogs/hi.json +223 -210
  300. package/src/i18n/catalogs/it.json +223 -210
  301. package/src/i18n/catalogs/ja.json +223 -210
  302. package/src/i18n/catalogs/pt.json +223 -210
  303. package/src/i18n/catalogs/zh.json +223 -210
@@ -0,0 +1,27 @@
1
+ import type { WorkflowKind } from './definitions.js';
2
+ export interface WorkflowTaskView {
3
+ id: string;
4
+ title: string;
5
+ closed: boolean;
6
+ order: number;
7
+ ad_hoc: boolean;
8
+ category?: string;
9
+ }
10
+ export interface WorkflowStageTasksView {
11
+ id: string;
12
+ title: string;
13
+ tasks: WorkflowTaskView[];
14
+ }
15
+ export interface WorkflowCardView {
16
+ code: string;
17
+ name: string;
18
+ kind: WorkflowKind;
19
+ status: 'open' | 'closed';
20
+ done: number;
21
+ total: number;
22
+ stages: WorkflowStageTasksView[];
23
+ }
24
+ /** Build the per-workflow card views (stages -> ordered tasks) for a
25
+ * project. Best-effort: a missing store yields an empty list. */
26
+ export declare function computeWorkflowsView(slug: string, status?: 'open' | 'all'): Promise<WorkflowCardView[]>;
27
+ //# sourceMappingURL=multi_view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi_view.d.ts","sourceRoot":"","sources":["../../src/workflow/multi_view.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AACD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC;AAOD;kEACkE;AAClE,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,KAAc,GAC5C,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA8C7B"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Multi-workflow view (PND-094 ext).
3
+ *
4
+ * The old computeWorkflowView produced ONE workflow from the legacy
5
+ * WorkflowState. The new model has several coexisting WorkflowInstances
6
+ * whose TASKS are pendings (linked via PendingItem.workflow). This
7
+ * crosses the instances with their task-pendings to produce, per
8
+ * workflow, its stages each with its ordered tasks -- the structure both
9
+ * the desktop panel and the mobile board render.
10
+ *
11
+ * ASCII-only.
12
+ */
13
+ import { listInstances } from './instances.js';
14
+ import { listPending } from '../pending/store.js';
15
+ function stripCode(code, title) {
16
+ const p = '[' + code + '] ';
17
+ return title.startsWith(p) ? title.slice(p.length) : title;
18
+ }
19
+ /** Build the per-workflow card views (stages -> ordered tasks) for a
20
+ * project. Best-effort: a missing store yields an empty list. */
21
+ export async function computeWorkflowsView(slug, status = 'open') {
22
+ let instances;
23
+ try {
24
+ instances = await listInstances(slug, status === 'all' ? 'all' : 'open');
25
+ }
26
+ catch {
27
+ return [];
28
+ }
29
+ if (instances.length === 0)
30
+ return [];
31
+ let allPend;
32
+ try {
33
+ allPend = await listPending(slug, { status: 'all' });
34
+ }
35
+ catch {
36
+ allPend = [];
37
+ }
38
+ const out = [];
39
+ for (const inst of instances) {
40
+ const tasks = allPend.filter((p) => p.workflow?.code === inst.code);
41
+ const byStage = new Map();
42
+ for (const t of tasks) {
43
+ const w = t.workflow;
44
+ const tv = {
45
+ id: t.id,
46
+ title: stripCode(inst.code, t.title),
47
+ closed: t.closed_at !== undefined,
48
+ order: w.order,
49
+ ad_hoc: w.ad_hoc === true,
50
+ ...(t.category ? { category: t.category } : {}),
51
+ };
52
+ const arr = byStage.get(w.stage_id) ?? [];
53
+ arr.push(tv);
54
+ byStage.set(w.stage_id, arr);
55
+ }
56
+ const stages = inst.stages.map((s) => ({
57
+ id: s.id, title: s.title,
58
+ tasks: (byStage.get(s.id) ?? []).sort((a, b) => a.order - b.order),
59
+ }));
60
+ /* Ad-hoc tasks may use a stage_id that is not in the instance
61
+ * skeleton -- surface them under their own stage so nothing is lost. */
62
+ const known = new Set(inst.stages.map((s) => s.id));
63
+ for (const [sid, arr] of byStage) {
64
+ if (!known.has(sid))
65
+ stages.push({ id: sid, title: sid, tasks: arr.sort((a, b) => a.order - b.order) });
66
+ }
67
+ out.push({
68
+ code: inst.code, name: inst.name, kind: inst.kind, status: inst.status,
69
+ done: tasks.filter((t) => t.closed_at !== undefined).length,
70
+ total: tasks.length,
71
+ stages,
72
+ });
73
+ }
74
+ return out;
75
+ }
76
+ //# sourceMappingURL=multi_view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi_view.js","sourceRoot":"","sources":["../../src/workflow/multi_view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ import { type WorkflowInstance } from './instances.js';
2
+ import type { WorkflowKind } from './definitions.js';
3
+ import type { PendingItem, PendingCategory } from '../pending/types.js';
4
+ /** True when the project already has an implementation. Pure fs scan:
5
+ * a package.json / known source dir, or >3 real top-level entries. */
6
+ export declare function projectHasCode(projectRoot: string): Promise<boolean>;
7
+ export interface ClassifyResult {
8
+ kind: WorkflowKind;
9
+ confidence: number;
10
+ rationale: string;
11
+ /** True when confidence is low -- the caller must ASK the user
12
+ * (decision: on doubt, confirm). */
13
+ needs_confirm: boolean;
14
+ }
15
+ export declare function classifyForProject(projectRoot: string, requestText: string): Promise<ClassifyResult>;
16
+ export interface InstantiateInput {
17
+ slug: string;
18
+ projectRoot: string;
19
+ kind: WorkflowKind;
20
+ name: string;
21
+ }
22
+ export interface InstantiateResult {
23
+ instance: WorkflowInstance;
24
+ tasks: PendingItem[];
25
+ }
26
+ /** Create a workflow instance + spawn one pending per canonical task,
27
+ * in mandatory order. Seeds the editable config (+ DR snapshot) first. */
28
+ export declare function instantiateWorkflow(input: InstantiateInput): Promise<InstantiateResult>;
29
+ /** Spawn ONE pending per canonical task of the instance's kind, in
30
+ * mandatory order, linked to the given EXISTING instance. The primitive
31
+ * shared by instantiateWorkflow and by upgrading a backlog-only shell so
32
+ * every phase gets its canonical scaffold (triage/diseno/.../cerrar). */
33
+ export declare function seedCanonicalTasks(slug: string, projectRoot: string, instance: WorkflowInstance): Promise<PendingItem[]>;
34
+ /** Create a workflow instance WITHOUT spawning canonical task pendings.
35
+ * Used when the tasks already exist (a backlog folded into a brownfield
36
+ * workflow via attachPendingsToWorkflow). */
37
+ export declare function createWorkflowShell(input: InstantiateInput): Promise<WorkflowInstance>;
38
+ /** Fold EXISTING pendings into a workflow as its tasks, in the given
39
+ * order (default: the order they are passed). Each gets a workflow
40
+ * link with a sequential `order` after any tasks already on the
41
+ * instance. Skips ids that do not exist. Returns the linked items. */
42
+ export declare function attachPendingsToWorkflow(input: {
43
+ slug: string;
44
+ code: string;
45
+ ids: string[];
46
+ stage_id?: string;
47
+ }): Promise<PendingItem[]>;
48
+ export interface RouteInput {
49
+ slug: string;
50
+ projectRoot: string;
51
+ kind: WorkflowKind;
52
+ name: string;
53
+ }
54
+ /** Find an OPEN instance with the same name (same initiative) or create
55
+ * a new one. Coexistence: instances are keyed by code + name, so two
56
+ * distinct initiatives of the same kind run side by side. */
57
+ export declare function routeRequest(input: RouteInput): Promise<{
58
+ instance: WorkflowInstance;
59
+ created: boolean;
60
+ }>;
61
+ export interface MapHookResult {
62
+ created: boolean;
63
+ kind?: WorkflowKind;
64
+ code?: string;
65
+ name?: string;
66
+ reason: string;
67
+ }
68
+ /** On mapping a project, ensure the RIGHT workflow exists -- deterministic,
69
+ * no LLM. greenfield (no code) -> instantiate the build skeleton (tasks
70
+ * spawned). brownfield (has code) -> an evolutive maintenance workflow
71
+ * WITH its canonical tasks per phase (triage/diseno/implementar/validar/
72
+ * docs/cerrar) spawned, so every phase has its canonical scaffold and no
73
+ * phase looks empty; ad-hoc backlog items attach under Implementar.
74
+ * Idempotent: a no-op when the project already has an open workflow, so
75
+ * it is safe to call on every scan/add. Best-effort -- callers must not
76
+ * let it break the map. */
77
+ export declare function ensureWorkflowForMappedProject(slug: string, projectRoot: string, projectName?: string): Promise<MapHookResult>;
78
+ export interface AddTaskInput {
79
+ slug: string;
80
+ code: string;
81
+ title: string;
82
+ body?: string;
83
+ category?: PendingCategory;
84
+ stage_id?: string;
85
+ priority?: number;
86
+ }
87
+ /** Append a task to a running workflow at the END of its order. Used
88
+ * for corrective/evolutive tasks the user adds at discretion during a
89
+ * workflow, AND for tasks the brain decides to add mid-execution. */
90
+ export declare function addTaskToWorkflow(input: AddTaskInput): Promise<PendingItem>;
91
+ /** All task-pendings of a workflow, sorted by mandatory order. */
92
+ export declare function workflowTasks(slug: string, code: string, status?: 'open' | 'closed' | 'all'): Promise<PendingItem[]>;
93
+ /** The next task to work: the open task with the lowest order. */
94
+ export declare function nextTask(slug: string, code: string): Promise<PendingItem | undefined>;
95
+ export interface OrderGateResult {
96
+ ok: boolean;
97
+ /** When !ok, the earlier-order open task that blocks this close. */
98
+ blocked_by?: {
99
+ id: string;
100
+ title: string;
101
+ order: number;
102
+ };
103
+ }
104
+ /** Mandatory ordering gate: a task may not close while an EARLIER-order
105
+ * task in the same workflow is still open. Non-workflow items always
106
+ * pass. The caller may override explicitly (force). */
107
+ export declare function canCloseTask(slug: string, id: string): Promise<OrderGateResult>;
108
+ /** After a task closes: if every task of its workflow is now closed,
109
+ * auto-close the instance. Returns the closed instance when it closed. */
110
+ export declare function onWorkflowTaskClosed(slug: string, code: string): Promise<WorkflowInstance | undefined>;
111
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/workflow/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Workflow orchestrator (PND-094 ext) -- DETERMINISTIC, no LLM.
3
+ *
4
+ * Ties the three layers together with plain code:
5
+ * - config.ts -- the editable stage/task definitions (+ DR).
6
+ * - instances.ts -- the running workflow instances (coexisting).
7
+ * - pending store -- the tasks (stages are NOT pendings; tasks are).
8
+ *
9
+ * What this module does, all deterministically:
10
+ * - classify a request (greenfield vs corrective vs evolutive) +
11
+ * flag when confidence is low so the caller ASKS the user.
12
+ * - instantiate a workflow: create the instance + spawn ONE pending
13
+ * per canonical task, in mandatory `order`.
14
+ * - add a task to a running workflow (user OR brain, ad-hoc).
15
+ * - enforce mandatory ordering on close (a task cannot close while an
16
+ * earlier-order task in the same workflow is still open).
17
+ * - auto-close the instance when all its tasks are closed.
18
+ *
19
+ * The LLM is NOT in this loop. It only does the WORK inside each task
20
+ * and (separately) translates NL config-edit requests into a patch.
21
+ *
22
+ * ASCII-only.
23
+ */
24
+ import { promises as fs } from 'node:fs';
25
+ import { classifyWorkflowKind } from './select.js';
26
+ import { resolveOrderedTasks, seedWorkflowConfigIfMissing } from './config.js';
27
+ import { createInstance, findInstance, findOpenByName, closeInstance, } from './instances.js';
28
+ import { resolveWorkflowDef } from './config.js';
29
+ import { addPending, listPending, } from '../pending/store.js';
30
+ /* ----- project code detection (deterministic heuristic) ----- */
31
+ const CODE_DIR_HINTS = ['src', 'app', 'lib', 'components', 'packages', 'pages'];
32
+ const IGNORE_ENTRIES = new Set(['.forge', '.git', '.github', 'node_modules', 'docs', 'dist', 'build']);
33
+ /** True when the project already has an implementation. Pure fs scan:
34
+ * a package.json / known source dir, or >3 real top-level entries. */
35
+ export async function projectHasCode(projectRoot) {
36
+ try {
37
+ const entries = await fs.readdir(projectRoot, { withFileTypes: true });
38
+ if (entries.some((e) => e.isFile() && e.name === 'package.json'))
39
+ return true;
40
+ if (entries.some((e) => e.isDirectory() && CODE_DIR_HINTS.includes(e.name)))
41
+ return true;
42
+ const real = entries.filter((e) => !e.name.startsWith('.') && !IGNORE_ENTRIES.has(e.name)
43
+ && !/^readme/i.test(e.name) && !/^license/i.test(e.name));
44
+ return real.length > 3;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ const CONFIRM_THRESHOLD = 0.6;
51
+ export async function classifyForProject(projectRoot, requestText) {
52
+ const hasExistingCode = await projectHasCode(projectRoot);
53
+ const r = classifyWorkflowKind({ text: requestText, hasExistingCode });
54
+ return { ...r, needs_confirm: r.confidence < CONFIRM_THRESHOLD };
55
+ }
56
+ /* ----- task <-> pending mapping ----- */
57
+ function taskCategory(gate) {
58
+ /* A gate task needs the owner's explicit OK; everything else Sumi can
59
+ * pick up unsupervised. */
60
+ return gate ? 'user_blocked' : 'autopilot';
61
+ }
62
+ function taskPriority(order) {
63
+ /* Cluster workflow tasks together + keep them in order in the normal
64
+ * pending list (priority asc). */
65
+ return Math.min(100, 20 + order);
66
+ }
67
+ /** Create a workflow instance + spawn one pending per canonical task,
68
+ * in mandatory order. Seeds the editable config (+ DR snapshot) first. */
69
+ export async function instantiateWorkflow(input) {
70
+ await seedWorkflowConfigIfMissing(input.projectRoot);
71
+ const def = await resolveWorkflowDef(input.projectRoot, input.kind);
72
+ const instance = await createInstance(input.slug, {
73
+ kind: input.kind,
74
+ name: input.name,
75
+ stages: def.stages.map((s) => ({ id: s.id, title: s.title })),
76
+ });
77
+ const tasks = await seedCanonicalTasks(input.slug, input.projectRoot, instance);
78
+ return { instance, tasks };
79
+ }
80
+ /** Spawn ONE pending per canonical task of the instance's kind, in
81
+ * mandatory order, linked to the given EXISTING instance. The primitive
82
+ * shared by instantiateWorkflow and by upgrading a backlog-only shell so
83
+ * every phase gets its canonical scaffold (triage/diseno/.../cerrar). */
84
+ export async function seedCanonicalTasks(slug, projectRoot, instance) {
85
+ const orderedTasks = await resolveOrderedTasks(projectRoot, instance.kind);
86
+ const tasks = [];
87
+ for (const t of orderedTasks) {
88
+ const add = {
89
+ title: '[' + instance.code + '] ' + t.title,
90
+ body: t.content,
91
+ category: taskCategory(t.gate),
92
+ priority: taskPriority(t.order),
93
+ workflow: { code: instance.code, kind: instance.kind, stage_id: t.stage_id, order: t.order },
94
+ ...(t.gate ? { blocker_kind: 'user_decision', blocker_who: 'pablo' } : {}),
95
+ };
96
+ tasks.push(await addPending(slug, add));
97
+ }
98
+ return tasks;
99
+ }
100
+ /** Create a workflow instance WITHOUT spawning canonical task pendings.
101
+ * Used when the tasks already exist (a backlog folded into a brownfield
102
+ * workflow via attachPendingsToWorkflow). */
103
+ export async function createWorkflowShell(input) {
104
+ await seedWorkflowConfigIfMissing(input.projectRoot);
105
+ const def = await resolveWorkflowDef(input.projectRoot, input.kind);
106
+ return createInstance(input.slug, {
107
+ kind: input.kind,
108
+ name: input.name,
109
+ stages: def.stages.map((s) => ({ id: s.id, title: s.title })),
110
+ });
111
+ }
112
+ /** Fold EXISTING pendings into a workflow as its tasks, in the given
113
+ * order (default: the order they are passed). Each gets a workflow
114
+ * link with a sequential `order` after any tasks already on the
115
+ * instance. Skips ids that do not exist. Returns the linked items. */
116
+ export async function attachPendingsToWorkflow(input) {
117
+ const inst = await findInstance(input.slug, input.code);
118
+ if (!inst)
119
+ throw new Error('attachPendingsToWorkflow: unknown workflow ' + input.code);
120
+ const existing = await workflowTasks(input.slug, input.code, 'all');
121
+ let order = existing.reduce((m, t) => Math.max(m, t.workflow?.order ?? -1), -1) + 1;
122
+ const stage_id = input.stage_id ?? inst.stages[0]?.id ?? 'stage';
123
+ const { setPendingWorkflow, findPending } = await import('../pending/store.js');
124
+ const out = [];
125
+ for (const id of input.ids) {
126
+ const found = await findPending(input.slug, id);
127
+ if (!found)
128
+ continue;
129
+ /* Attached backlog items are INDEPENDENT (not canonical sequential
130
+ * steps), so they are ad_hoc -> exempt from the ordering gate. */
131
+ const linked = await setPendingWorkflow(input.slug, id, {
132
+ code: inst.code, kind: inst.kind, stage_id, order, ad_hoc: true,
133
+ });
134
+ out.push(linked);
135
+ order += 1;
136
+ }
137
+ return out;
138
+ }
139
+ /** Find an OPEN instance with the same name (same initiative) or create
140
+ * a new one. Coexistence: instances are keyed by code + name, so two
141
+ * distinct initiatives of the same kind run side by side. */
142
+ export async function routeRequest(input) {
143
+ const existing = await findOpenByName(input.slug, input.name);
144
+ if (existing && existing.kind === input.kind)
145
+ return { instance: existing, created: false };
146
+ const { instance } = await instantiateWorkflow(input);
147
+ return { instance, created: true };
148
+ }
149
+ /** On mapping a project, ensure the RIGHT workflow exists -- deterministic,
150
+ * no LLM. greenfield (no code) -> instantiate the build skeleton (tasks
151
+ * spawned). brownfield (has code) -> an evolutive maintenance workflow
152
+ * WITH its canonical tasks per phase (triage/diseno/implementar/validar/
153
+ * docs/cerrar) spawned, so every phase has its canonical scaffold and no
154
+ * phase looks empty; ad-hoc backlog items attach under Implementar.
155
+ * Idempotent: a no-op when the project already has an open workflow, so
156
+ * it is safe to call on every scan/add. Best-effort -- callers must not
157
+ * let it break the map. */
158
+ export async function ensureWorkflowForMappedProject(slug, projectRoot, projectName) {
159
+ const { listInstances } = await import('./instances.js');
160
+ const open = await listInstances(slug, 'open');
161
+ if (open.length > 0) {
162
+ return { created: false, reason: 'ya hay un workflow abierto (' + open[0].code + ')' };
163
+ }
164
+ const label = (projectName && projectName.trim()) || slug;
165
+ const hasCode = await projectHasCode(projectRoot);
166
+ if (hasCode) {
167
+ const { instance } = await instantiateWorkflow({ slug, projectRoot, kind: 'evolutive', name: label + ' -- mantenimiento' });
168
+ return { created: true, kind: 'evolutive', code: instance.code, name: instance.name, reason: 'brownfield (el proyecto ya tiene codigo) -> workflow evolutivo con tareas canonicas por fase' };
169
+ }
170
+ const { instance } = await instantiateWorkflow({ slug, projectRoot, kind: 'greenfield', name: label + ' -- build' });
171
+ return { created: true, kind: 'greenfield', code: instance.code, name: instance.name, reason: 'greenfield (sin codigo) -> skeleton de 18 pasos' };
172
+ }
173
+ /** Append a task to a running workflow at the END of its order. Used
174
+ * for corrective/evolutive tasks the user adds at discretion during a
175
+ * workflow, AND for tasks the brain decides to add mid-execution. */
176
+ export async function addTaskToWorkflow(input) {
177
+ const inst = await findInstance(input.slug, input.code);
178
+ if (!inst)
179
+ throw new Error('addTaskToWorkflow: unknown workflow ' + input.code);
180
+ if (inst.status !== 'open')
181
+ throw new Error('addTaskToWorkflow: workflow ' + input.code + ' is closed');
182
+ const tasks = await workflowTasks(input.slug, input.code, 'all');
183
+ const nextOrder = tasks.reduce((m, t) => Math.max(m, t.workflow?.order ?? 0), -1) + 1;
184
+ const stage_id = input.stage_id ?? inst.stages[inst.stages.length - 1]?.id ?? 'ad-hoc';
185
+ return addPending(input.slug, {
186
+ title: '[' + inst.code + '] ' + input.title,
187
+ ...(input.body ? { body: input.body } : {}),
188
+ category: input.category ?? 'autopilot',
189
+ priority: input.priority ?? taskPriority(nextOrder),
190
+ workflow: { code: inst.code, kind: inst.kind, stage_id, order: nextOrder, ad_hoc: true },
191
+ });
192
+ }
193
+ /* ----- queries + gates ----- */
194
+ /** All task-pendings of a workflow, sorted by mandatory order. */
195
+ export async function workflowTasks(slug, code, status = 'all') {
196
+ const all = await listPending(slug, { status });
197
+ return all
198
+ .filter((p) => p.workflow?.code === code)
199
+ .sort((a, b) => (a.workflow.order - b.workflow.order));
200
+ }
201
+ /** The next task to work: the open task with the lowest order. */
202
+ export async function nextTask(slug, code) {
203
+ const open = await workflowTasks(slug, code, 'open');
204
+ return open[0];
205
+ }
206
+ /** Mandatory ordering gate: a task may not close while an EARLIER-order
207
+ * task in the same workflow is still open. Non-workflow items always
208
+ * pass. The caller may override explicitly (force). */
209
+ export async function canCloseTask(slug, id) {
210
+ const all = await listPending(slug, { status: 'all' });
211
+ const item = all.find((p) => p.id === id);
212
+ if (!item || !item.workflow)
213
+ return { ok: true };
214
+ /* ad_hoc tasks (folded-in backlog items) are INDEPENDENT -- they are
215
+ * never gated, and they never block a canonical step either. The gate
216
+ * applies only among the canonical sequential steps. */
217
+ if (item.workflow.ad_hoc)
218
+ return { ok: true };
219
+ const earlierOpen = all
220
+ .filter((p) => p.workflow?.code === item.workflow.code
221
+ && p.closed_at === undefined
222
+ && !p.workflow.ad_hoc
223
+ && (p.workflow.order < item.workflow.order))
224
+ .sort((a, b) => a.workflow.order - b.workflow.order)[0];
225
+ if (earlierOpen) {
226
+ return { ok: false, blocked_by: { id: earlierOpen.id, title: earlierOpen.title, order: earlierOpen.workflow.order } };
227
+ }
228
+ return { ok: true };
229
+ }
230
+ /** After a task closes: if every task of its workflow is now closed,
231
+ * auto-close the instance. Returns the closed instance when it closed. */
232
+ export async function onWorkflowTaskClosed(slug, code) {
233
+ const open = await workflowTasks(slug, code, 'open');
234
+ if (open.length > 0)
235
+ return undefined;
236
+ const all = await workflowTasks(slug, code, 'all');
237
+ if (all.length === 0)
238
+ return undefined; /* nothing to close on */
239
+ return closeInstance(slug, code);
240
+ }
241
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/workflow/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -118,3 +118,35 @@ yujin-design-system/
118
118
  - **Director**: when the user explicitly requests an override
119
119
  ("use shadcn"), invokes `yujin.design.override` instead of
120
120
  silently accepting. The R8 modal confirms.
121
+
122
+ ## Variants -- selectable design systems (PND-112)
123
+
124
+ The Yujin DS ships in two variants. The sumi-e one is the
125
+ DEFAULT; the art deco one is opt-in per product / panel.
126
+
127
+ - **`yujin-design-system`** (default) -- sumi-e aesthetic:
128
+ indigo/teal/amber tones, 170 sumi-e icons, kanji wordmarks.
129
+ - **`yujin-design-system-artdeco`** -- pastel art deco: powder
130
+ blues + warm slate grays + creams + a sparing brass rule,
131
+ Poiret One / Josefin Sans typography, 48 geometric art deco
132
+ icons. NO kanji, NO sumi-e. Crisper geometry (radii 2/4/8).
133
+
134
+ Both expose the SAME semantic token contract (`--color-accent`,
135
+ `--color-bg-*`, `--color-text-*`, `--color-border-*`, state
136
+ colors) and SHARE the same 30 components (theme-agnostic --
137
+ they consume `var(--color-*)`), so picking a variant is purely
138
+ a token + icon swap, never a component rewrite.
139
+
140
+ Selection: the resolver (`src/design/yujin_design_resolver.ts`)
141
+ takes a `ds` selector on every reader (`getManifest({ds})`,
142
+ `getTokensCss({ds})`, `listIcons(tag,{ds})`, `getIconSvg`,
143
+ `listTemplates`, `getTemplate`). `ds: 'artdeco'` -> the pastel
144
+ variant; absent / `'sumie'` / `'default'` -> the sumi-e default.
145
+ `getTokensCss({ds})` returns the theme CSS a generated product
146
+ or the panel injects to apply the look.
147
+
148
+ When a product should use the art deco look (signals: "art
149
+ deco", "pastel", "elegante geometrico", "sin kanjis", "estetica
150
+ clasica/dorada"), select the artdeco variant; otherwise keep the
151
+ sumi-e default. The icon catalog of the SELECTED variant is the
152
+ only one to pull from (no mixing sets).
@@ -100,3 +100,23 @@ similar. The verbs are cross-platform; no shell needed.
100
100
  the doc is long.
101
101
  - Pair `office.*.write` with R8 modal (policy=approval-required;
102
102
  user confirms before disk write).
103
+
104
+ ## Opening vs reading (desktop.open vs office.*.read)
105
+
106
+ There are TWO different intents -- pick by what the user wants:
107
+
108
+ - **OPEN / SHOW it to the user** ("abri la planilla", "open this Excel",
109
+ "show me the doc") -> `desktop.open({target})`. It launches the file
110
+ in its native app (.xlsx -> Excel, .docx -> Word, .pdf -> the viewer)
111
+ or, for a Google Sheets/Docs URL or a `.gsheet`/`.gdoc` shortcut, in
112
+ the browser. This is the right move when the human wants to SEE it.
113
+
114
+ - **READ / COMPUTE over the data** ("what's the total", "extract the
115
+ rows", "summarize the doc") -> `office.excel.read` / `office.word.read`
116
+ / `office.pdf.read`. These return structured data for YOU to reason
117
+ over.
118
+
119
+ NEVER open a binary office file as a pizarron editor tab
120
+ (`forge_open_file_for_editor` / fs.read-file): the bytes render as
121
+ noise and FREEZE the panel (PND-102). The open-file verb now refuses
122
+ office/binary extensions and points here.
@@ -50,3 +50,43 @@ R7 -- HONEST SEQUENCING (anti-hallucination cont.):
50
50
  then yujin.git.commit. Three chained invokes. Your chat
51
51
  reply summarises the 3 actions AFTER all 3 returned
52
52
  result_ok=true.
53
+
54
+ KIND SELECTION (MANDATORY) -- choose the create-tab kind BEFORE
55
+ you invoke. This is a hard rule (invariant level, like R1-R8);
56
+ do NOT improvise. Map the request to a kind by this table:
57
+
58
+ | Request words / intent | kind |
59
+ |-----------------------------------------------------|-------|
60
+ | Flow / flujo / flowchart / proceso / circuito / | bpmn |
61
+ | "los pasos de X" / diagrama de proceso / BPMN | |
62
+ | Relaciones / dependencias / "que usa que" / grafo | graph |
63
+ | del proyecto / nodos sin orden | |
64
+ | Documento / reporte / spec / analisis / diseño / | doc |
65
+ | arquitectura / propuesta / how-to | |
66
+ | Codigo fuente | code |
67
+ | Datos tabulares | table |
68
+
69
+ PROHIBITED: kind="graph" for a process/flow. The graph is for
70
+ relations/dependencies WITHOUT order; a flow has a start, an
71
+ end and ordered steps.
72
+
73
+ Tie-breaker (bpmn vs graph): does the thing have a START and an
74
+ END and ordered STEPS / decisions? -> bpmn. Is it a web of
75
+ relations with no inherent order? -> graph.
76
+
77
+ bpmn content shape (JSON string):
78
+ {"lanes":[{"id","label"}] (optional swimlanes),
79
+ "nodes":[{"id","type","label","lane"?,"gateway"?}],
80
+ "flows":[{"from","to","label"?}]}
81
+ type in startEvent | endEvent | intermediate | task |
82
+ userTask | serviceTask | scriptTask | sendTask |
83
+ receiveTask | gateway
84
+ gateway in exclusive | parallel | inclusive
85
+
86
+ graph content shape (JSON string):
87
+ {"nodes":[{"id","label","weight"?,"kind"?,"detail"?}],
88
+ "edges":[{"from","to","kind"?,"label"?}]}
89
+
90
+ Anti-pattern this prevents (see docs/GOTCHAS.md): rendering a
91
+ business flow with kind="graph". The user asks for a FLUJO and
92
+ gets a force-directed node web instead of a BPMN diagram.
@@ -59,6 +59,22 @@ In those cases, invoke `yujin.shell.exec` directly. The classifier
59
59
  will gate destructive / network / elevation commands behind the
60
60
  approval modal; safe ones auto-approve.
61
61
 
62
+ ## Long-running commands -> yujin.task.run (MANDATORY)
63
+
64
+ `yujin.shell.exec` runs SYNCHRONOUSLY: it blocks the turn and the
65
+ child process is killed when the turn ends. So a command that does NOT
66
+ terminate on its own -- a dev server, a watcher, `tail -f`, a tunnel
67
+ (`npm/pnpm run dev|start|serve|watch`, `expo start`, `vite`,
68
+ `next dev`, `nodemon`, `wrangler dev`, `docker compose up`,
69
+ `cloudflared tunnel`, ...) -- MUST be launched with `yujin.task.run`,
70
+ which runs it detached so it SURVIVES the turn. Follow it with
71
+ `yujin.task.status` / `yujin.task.list`; the user stops or deletes it
72
+ from the Tareas tab in the pizarron.
73
+
74
+ shell.exec ENFORCES this: it refuses such commands and points you to
75
+ `yujin.task.run` (error `long_running_must_use_task`). Only pass
76
+ `allow_long_running:true` in the rare case you truly need it in-turn.
77
+
62
78
  ## When to fetch this doctrine
63
79
 
64
80
  Fetch when: