@jaimevalasek/aioson 1.7.2 → 1.8.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 (362) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +153 -10
  3. package/docs/en/cli-reference.md +56 -1
  4. package/docs/en/i18n.md +18 -18
  5. package/docs/en/schemas/index.json +10 -0
  6. package/docs/en/schemas/parallel-assign.schema.json +9 -0
  7. package/docs/en/schemas/parallel-doctor.schema.json +36 -0
  8. package/docs/en/schemas/parallel-guard.schema.json +63 -0
  9. package/docs/en/schemas/parallel-merge.schema.json +84 -0
  10. package/docs/en/schemas/parallel-status.schema.json +91 -1
  11. package/docs/integrations/apps-publish-marketplace.md +94 -0
  12. package/docs/pt/README.md +9 -0
  13. package/docs/pt/agentes.md +324 -3
  14. package/docs/pt/clientes-ai.md +7 -3
  15. package/docs/pt/comandos-cli.md +160 -13
  16. package/docs/pt/compress-agents.md +304 -0
  17. package/docs/pt/design-docs-governance.md +59 -0
  18. package/docs/pt/feature-archive.md +191 -0
  19. package/docs/pt/genome-3.0-spec.md +115 -4
  20. package/docs/pt/genome-distribution.md +232 -0
  21. package/docs/pt/inicio-rapido.md +1 -0
  22. package/docs/pt/motor-hardening.md +492 -0
  23. package/docs/pt/runner-system.md +113 -0
  24. package/package.json +2 -1
  25. package/src/agent-manifests.js +66 -0
  26. package/src/agents.js +27 -7
  27. package/src/autonomy-policy.js +139 -0
  28. package/src/brain-query.js +161 -0
  29. package/src/cli.js +1377 -1099
  30. package/src/commands/agents.js +102 -7
  31. package/src/commands/artifact-validate.js +33 -4
  32. package/src/commands/auth.js +272 -0
  33. package/src/commands/brain-query.js +44 -0
  34. package/src/commands/briefing.js +344 -0
  35. package/src/commands/commit-prepare.js +547 -0
  36. package/src/commands/compress-agents.js +416 -0
  37. package/src/commands/context-health.js +4 -2
  38. package/src/commands/context-trim.js +17 -11
  39. package/src/commands/design-hybrid-options.js +3 -3
  40. package/src/commands/devlog-process.js +6 -4
  41. package/src/commands/dossier.js +423 -0
  42. package/src/commands/feature-archive.js +513 -0
  43. package/src/commands/feature-close.js +123 -18
  44. package/src/commands/gate-approve.js +198 -0
  45. package/src/commands/gate-check.js +24 -5
  46. package/src/commands/genome-doctor.js +166 -9
  47. package/src/commands/git-guard.js +170 -0
  48. package/src/commands/harness.js +121 -0
  49. package/src/commands/implementation-plan.js +47 -20
  50. package/src/commands/init.js +6 -2
  51. package/src/commands/install.js +6 -2
  52. package/src/commands/live.js +497 -56
  53. package/src/commands/locale-apply.js +9 -6
  54. package/src/commands/locale-diff.js +11 -112
  55. package/src/commands/mcp-doctor.js +2 -1
  56. package/src/commands/mcp-init.js +4 -10
  57. package/src/commands/memory.js +234 -0
  58. package/src/commands/parallel-assign.js +107 -27
  59. package/src/commands/parallel-doctor.js +416 -3
  60. package/src/commands/parallel-guard.js +241 -0
  61. package/src/commands/parallel-init.js +66 -4
  62. package/src/commands/parallel-merge.js +299 -0
  63. package/src/commands/parallel-status.js +147 -3
  64. package/src/commands/preflight.js +63 -4
  65. package/src/commands/qa-init.js +10 -5
  66. package/src/commands/revision.js +235 -0
  67. package/src/commands/scaffold-complete.js +188 -0
  68. package/src/commands/security-audit.js +275 -0
  69. package/src/commands/security-scan.js +376 -0
  70. package/src/commands/self-implement-loop.js +46 -2
  71. package/src/commands/setup-context.js +11 -10
  72. package/src/commands/squad-agent-create.js +51 -9
  73. package/src/commands/squad-investigate.js +53 -0
  74. package/src/commands/squad-plan.js +33 -1
  75. package/src/commands/squad-scaffold.js +4 -3
  76. package/src/commands/squad-score.js +71 -14
  77. package/src/commands/squad-status.js +22 -1
  78. package/src/commands/squad-validate.js +93 -2
  79. package/src/commands/store-genome.js +304 -0
  80. package/src/commands/store-skill.js +247 -0
  81. package/src/commands/store-squad.js +431 -0
  82. package/src/commands/store-system.js +392 -0
  83. package/src/commands/tool-capabilities.js +63 -0
  84. package/src/commands/update.js +3 -3
  85. package/src/commands/verify-gate.js +40 -0
  86. package/src/commands/workflow-execute.js +644 -155
  87. package/src/commands/workflow-harden.js +231 -0
  88. package/src/commands/workflow-heal.js +136 -0
  89. package/src/commands/workflow-next.js +460 -22
  90. package/src/commands/workflow-status.js +328 -138
  91. package/src/commands/workspace.js +144 -0
  92. package/src/constants.js +42 -75
  93. package/src/context-memory.js +133 -4
  94. package/src/context-writer.js +2 -1
  95. package/src/context.js +32 -2
  96. package/src/doctor.js +46 -6
  97. package/src/dossier/codemap-store.js +267 -0
  98. package/src/dossier/dossier-bootstrap.js +222 -0
  99. package/src/dossier/dossier-compact.js +159 -0
  100. package/src/dossier/lock.js +128 -0
  101. package/src/dossier/revision-store.js +313 -0
  102. package/src/dossier/schema.js +155 -0
  103. package/src/dossier/store.js +400 -0
  104. package/src/execution-gateway.js +3 -0
  105. package/src/friction-scanner.js +202 -0
  106. package/src/genome-schema.js +24 -1
  107. package/src/genomes.js +33 -0
  108. package/src/handoff-contract.js +363 -0
  109. package/src/handoff-validator.js +45 -0
  110. package/src/harness/circuit-breaker.js +135 -0
  111. package/src/i18n/messages/en.js +317 -22
  112. package/src/i18n/messages/es.js +259 -18
  113. package/src/i18n/messages/fr.js +260 -18
  114. package/src/i18n/messages/pt-BR.js +313 -22
  115. package/src/install-profile.js +0 -16
  116. package/src/installer.js +70 -6
  117. package/src/lib/git-commit-guard.js +691 -0
  118. package/src/lib/security/artifact-reader.js +167 -0
  119. package/src/lib/security/exit-codes.js +51 -0
  120. package/src/lib/security/findings-writer.js +176 -0
  121. package/src/lib/security/runtime-events.js +77 -0
  122. package/src/lib/security/secrets-regex.js +115 -0
  123. package/src/lib/store/security-scan.js +173 -0
  124. package/src/lib/terminal-checkbox.js +130 -0
  125. package/src/lib/tmux-launcher.js +163 -0
  126. package/src/lib/tool-capabilities.js +102 -0
  127. package/src/locales.js +12 -8
  128. package/src/parallel-workspace.js +756 -0
  129. package/src/parser.js +8 -1
  130. package/src/path-guard.js +47 -0
  131. package/src/preflight-engine.js +237 -26
  132. package/src/self-healing.js +142 -0
  133. package/src/session-handoff.js +111 -1
  134. package/src/squad/squad-scaffold.js +183 -19
  135. package/src/test-briefing.js +226 -0
  136. package/src/updater.js +1 -1
  137. package/src/utils.js +3 -0
  138. package/src/workflow-gates.js +185 -0
  139. package/template/.aioson/agents/analyst.md +76 -130
  140. package/template/.aioson/agents/architect.md +53 -86
  141. package/template/.aioson/agents/committer.md +161 -0
  142. package/template/.aioson/agents/cypher.md +252 -0
  143. package/template/.aioson/agents/dev.md +112 -628
  144. package/template/.aioson/agents/deyvin.md +33 -236
  145. package/template/.aioson/agents/discover.md +235 -0
  146. package/template/.aioson/agents/discovery-design-doc.md +17 -252
  147. package/template/.aioson/agents/genome.md +76 -26
  148. package/template/.aioson/agents/manifests/analyst.manifest.json +26 -0
  149. package/template/.aioson/agents/manifests/architect.manifest.json +23 -0
  150. package/template/.aioson/agents/manifests/committer.manifest.json +23 -0
  151. package/template/.aioson/agents/manifests/dev.manifest.json +37 -0
  152. package/template/.aioson/agents/manifests/orchestrator.manifest.json +30 -0
  153. package/template/.aioson/agents/manifests/pentester.manifest.json +39 -0
  154. package/template/.aioson/agents/manifests/pm.manifest.json +26 -0
  155. package/template/.aioson/agents/manifests/product.manifest.json +23 -0
  156. package/template/.aioson/agents/manifests/qa.manifest.json +25 -0
  157. package/template/.aioson/agents/manifests/setup.manifest.json +20 -0
  158. package/template/.aioson/agents/manifests/ux-ui.manifest.json +24 -0
  159. package/template/.aioson/agents/neo.md +5 -7
  160. package/template/.aioson/agents/orache.md +2 -6
  161. package/template/.aioson/agents/orchestrator.md +81 -182
  162. package/template/.aioson/agents/pentester.md +235 -0
  163. package/template/.aioson/agents/pm.md +40 -104
  164. package/template/.aioson/agents/product.md +99 -344
  165. package/template/.aioson/agents/profiler-enricher.md +57 -6
  166. package/template/.aioson/agents/profiler-forge.md +17 -7
  167. package/template/.aioson/agents/profiler-researcher.md +29 -6
  168. package/template/.aioson/agents/qa.md +168 -514
  169. package/template/.aioson/agents/setup.md +52 -278
  170. package/template/.aioson/agents/sheldon.md +122 -754
  171. package/template/.aioson/agents/site-forge.md +111 -1583
  172. package/template/.aioson/agents/squad.md +139 -2010
  173. package/template/.aioson/agents/tester.md +10 -0
  174. package/template/.aioson/agents/ux-ui.md +104 -812
  175. package/template/.aioson/agents/validator.md +69 -0
  176. package/template/.aioson/brains/scripts/query.js +5 -1
  177. package/template/.aioson/config/autonomy-protocol.json +43 -0
  178. package/template/.aioson/config.md +43 -15
  179. package/template/.aioson/constitution.md +36 -33
  180. package/template/.aioson/context/design-doc.md +136 -0
  181. package/template/.aioson/context/project-map.md +57 -0
  182. package/template/.aioson/design-docs/code-reuse.md +48 -0
  183. package/template/.aioson/design-docs/componentization.md +47 -0
  184. package/template/.aioson/design-docs/file-size.md +52 -0
  185. package/template/.aioson/design-docs/folder-structure.md +51 -0
  186. package/template/.aioson/design-docs/naming.md +54 -0
  187. package/template/.aioson/docs/LAYERS.md +12 -2
  188. package/template/.aioson/docs/dev/execution-discipline.md +106 -0
  189. package/template/.aioson/docs/dev/stack-conventions.md +83 -0
  190. package/template/.aioson/docs/deyvin/continuity-recovery.md +57 -0
  191. package/template/.aioson/docs/deyvin/debugging-escalation.md +30 -0
  192. package/template/.aioson/docs/deyvin/pair-execution.md +44 -0
  193. package/template/.aioson/docs/deyvin/runtime-handoffs.md +36 -0
  194. package/template/.aioson/docs/product/conversation-playbook.md +116 -0
  195. package/template/.aioson/docs/product/prd-contract.md +107 -0
  196. package/template/.aioson/docs/product/quality-lens.md +57 -0
  197. package/template/.aioson/docs/product/research-loop.md +65 -0
  198. package/template/.aioson/docs/sheldon/enrichment-paths.md +134 -0
  199. package/template/.aioson/docs/sheldon/quality-lens.md +57 -0
  200. package/template/.aioson/docs/sheldon/research-loop.md +56 -0
  201. package/template/.aioson/docs/sheldon/web-intelligence.md +75 -0
  202. package/template/.aioson/docs/site-forge-build.md +195 -0
  203. package/template/.aioson/docs/site-forge-extraction.md +135 -0
  204. package/template/.aioson/docs/site-forge-qa.md +155 -0
  205. package/template/.aioson/docs/site-forge-recon.md +434 -0
  206. package/template/.aioson/docs/site-forge-transform.md +249 -0
  207. package/template/.aioson/docs/squad/content-output.md +91 -0
  208. package/template/.aioson/docs/squad/creation-flow.md +135 -0
  209. package/template/.aioson/docs/squad/domain-classification.md +117 -0
  210. package/template/.aioson/docs/squad/genome-bindings.md +47 -0
  211. package/template/.aioson/docs/squad/package-contract.md +234 -0
  212. package/template/.aioson/docs/squad/quality-lens.md +56 -0
  213. package/template/.aioson/docs/squad/research-loop.md +59 -0
  214. package/template/.aioson/docs/squad/session-operations.md +117 -0
  215. package/template/.aioson/docs/squad/workflow-quality.md +165 -0
  216. package/template/.aioson/docs/ux-ui/accessibility-audit.md +55 -0
  217. package/template/.aioson/docs/ux-ui/audit-mode.md +86 -0
  218. package/template/.aioson/docs/ux-ui/component-map.md +35 -0
  219. package/template/.aioson/docs/ux-ui/design-execution.md +111 -0
  220. package/template/.aioson/docs/ux-ui/design-gate.md +27 -0
  221. package/template/.aioson/docs/ux-ui/research-mode.md +39 -0
  222. package/template/.aioson/docs/ux-ui/site-delivery.md +156 -0
  223. package/template/.aioson/docs/ux-ui/token-contract.md +57 -0
  224. package/template/.aioson/genomes/copywriting.meta.json +48 -0
  225. package/template/.aioson/git-guard.json +11 -0
  226. package/template/.aioson/mcp/servers.md +0 -1
  227. package/template/.aioson/rules/agent-language-policy.md +93 -0
  228. package/template/.aioson/rules/aioson-context-boundary.md +63 -0
  229. package/template/.aioson/rules/canonical-path-contract.md +47 -0
  230. package/template/.aioson/rules/data-format-convention.md +24 -86
  231. package/template/.aioson/rules/disk-first-artifacts.md +44 -0
  232. package/template/.aioson/rules/output-brevity.md +44 -0
  233. package/template/.aioson/rules/prd-section-ownership.md +49 -0
  234. package/template/.aioson/rules/security-baseline.md +139 -0
  235. package/template/.aioson/rules/spec-level-ownership.md +61 -0
  236. package/template/.aioson/rules/squad-driver-pattern.md +81 -0
  237. package/template/.aioson/schemas/squad-blueprint.schema.json +24 -0
  238. package/template/.aioson/schemas/squad-manifest.schema.json +44 -0
  239. package/template/.aioson/skills/process/aioson-spec-driven/references/pm.md +30 -0
  240. package/template/.aioson/skills/process/secure-tdd/SKILL.md +97 -0
  241. package/template/.aioson/skills/process/secure-tdd/references/nextjs.md +81 -0
  242. package/template/.aioson/skills/process/secure-tdd/references/node-express.md +91 -0
  243. package/template/.aioson/skills/process/secure-tdd/references/planned-stacks.md +33 -0
  244. package/template/.aioson/skills/static/harness-validate/SKILL.md +46 -0
  245. package/template/.aioson/skills/static/web-research-cache.md +3 -0
  246. package/template/.aioson/tasks/squad-create.md +35 -8
  247. package/template/.aioson/tasks/squad-design.md +50 -2
  248. package/template/.aioson/tasks/squad-investigate.md +14 -1
  249. package/template/.claude/commands/aioson/agent/committer.md +5 -0
  250. package/template/.claude/commands/aioson/agent/copywriter.md +5 -0
  251. package/template/.claude/commands/aioson/agent/cypher.md +5 -0
  252. package/template/.claude/commands/aioson/agent/pair.md +5 -0
  253. package/template/.claude/commands/aioson/agent/validator.md +5 -0
  254. package/template/.gemini/commands/aios-analyst.toml +6 -3
  255. package/template/.gemini/commands/aios-architect.toml +7 -6
  256. package/template/.gemini/commands/aios-committer.toml +7 -0
  257. package/template/.gemini/commands/aios-copywriter.toml +7 -0
  258. package/template/.gemini/commands/aios-cypher.toml +7 -0
  259. package/template/.gemini/commands/aios-dev.toml +8 -7
  260. package/template/.gemini/commands/aios-deyvin.toml +6 -5
  261. package/template/.gemini/commands/aios-discovery-design-doc.toml +6 -3
  262. package/template/.gemini/commands/aios-genome.toml +7 -0
  263. package/template/.gemini/commands/aios-neo.toml +5 -3
  264. package/template/.gemini/commands/aios-orache.toml +7 -0
  265. package/template/.gemini/commands/aios-orchestrator.toml +8 -7
  266. package/template/.gemini/commands/aios-pair.toml +6 -5
  267. package/template/.gemini/commands/aios-pm.toml +8 -7
  268. package/template/.gemini/commands/aios-product.toml +5 -3
  269. package/template/.gemini/commands/aios-qa.toml +6 -5
  270. package/template/.gemini/commands/aios-setup.toml +5 -2
  271. package/template/.gemini/commands/aios-sheldon.toml +7 -0
  272. package/template/.gemini/commands/aios-site-forge.toml +7 -0
  273. package/template/.gemini/commands/aios-squad.toml +7 -0
  274. package/template/.gemini/commands/aios-tester.toml +6 -5
  275. package/template/.gemini/commands/aios-ux-ui.toml +8 -7
  276. package/template/.gemini/commands/aios-validator.toml +7 -0
  277. package/template/AGENTS.md +12 -1
  278. package/template/CLAUDE.md +5 -1
  279. package/template/.aioson/locales/en/agents/analyst.md +0 -244
  280. package/template/.aioson/locales/en/agents/architect.md +0 -245
  281. package/template/.aioson/locales/en/agents/dev.md +0 -397
  282. package/template/.aioson/locales/en/agents/deyvin.md +0 -137
  283. package/template/.aioson/locales/en/agents/discovery-design-doc.md +0 -27
  284. package/template/.aioson/locales/en/agents/genome.md +0 -212
  285. package/template/.aioson/locales/en/agents/neo.md +0 -8
  286. package/template/.aioson/locales/en/agents/orache.md +0 -6
  287. package/template/.aioson/locales/en/agents/orchestrator.md +0 -189
  288. package/template/.aioson/locales/en/agents/pair.md +0 -5
  289. package/template/.aioson/locales/en/agents/pm.md +0 -84
  290. package/template/.aioson/locales/en/agents/product.md +0 -378
  291. package/template/.aioson/locales/en/agents/profiler-enricher.md +0 -5
  292. package/template/.aioson/locales/en/agents/profiler-forge.md +0 -5
  293. package/template/.aioson/locales/en/agents/profiler-researcher.md +0 -5
  294. package/template/.aioson/locales/en/agents/qa.md +0 -270
  295. package/template/.aioson/locales/en/agents/setup.md +0 -421
  296. package/template/.aioson/locales/en/agents/sheldon.md +0 -455
  297. package/template/.aioson/locales/en/agents/squad.md +0 -449
  298. package/template/.aioson/locales/en/agents/tester.md +0 -6
  299. package/template/.aioson/locales/en/agents/ux-ui.md +0 -668
  300. package/template/.aioson/locales/es/agents/analyst.md +0 -225
  301. package/template/.aioson/locales/es/agents/architect.md +0 -245
  302. package/template/.aioson/locales/es/agents/dev.md +0 -370
  303. package/template/.aioson/locales/es/agents/deyvin.md +0 -99
  304. package/template/.aioson/locales/es/agents/discovery-design-doc.md +0 -21
  305. package/template/.aioson/locales/es/agents/genome.md +0 -104
  306. package/template/.aioson/locales/es/agents/neo.md +0 -50
  307. package/template/.aioson/locales/es/agents/orache.md +0 -105
  308. package/template/.aioson/locales/es/agents/orchestrator.md +0 -194
  309. package/template/.aioson/locales/es/agents/pair.md +0 -7
  310. package/template/.aioson/locales/es/agents/pm.md +0 -90
  311. package/template/.aioson/locales/es/agents/product.md +0 -372
  312. package/template/.aioson/locales/es/agents/profiler-enricher.md +0 -7
  313. package/template/.aioson/locales/es/agents/profiler-forge.md +0 -7
  314. package/template/.aioson/locales/es/agents/profiler-researcher.md +0 -7
  315. package/template/.aioson/locales/es/agents/qa.md +0 -198
  316. package/template/.aioson/locales/es/agents/setup.md +0 -405
  317. package/template/.aioson/locales/es/agents/sheldon.md +0 -309
  318. package/template/.aioson/locales/es/agents/squad.md +0 -532
  319. package/template/.aioson/locales/es/agents/tester.md +0 -9
  320. package/template/.aioson/locales/es/agents/ux-ui.md +0 -212
  321. package/template/.aioson/locales/fr/agents/analyst.md +0 -225
  322. package/template/.aioson/locales/fr/agents/architect.md +0 -245
  323. package/template/.aioson/locales/fr/agents/dev.md +0 -370
  324. package/template/.aioson/locales/fr/agents/deyvin.md +0 -99
  325. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +0 -21
  326. package/template/.aioson/locales/fr/agents/genome.md +0 -104
  327. package/template/.aioson/locales/fr/agents/neo.md +0 -50
  328. package/template/.aioson/locales/fr/agents/orache.md +0 -106
  329. package/template/.aioson/locales/fr/agents/orchestrator.md +0 -194
  330. package/template/.aioson/locales/fr/agents/pair.md +0 -7
  331. package/template/.aioson/locales/fr/agents/pm.md +0 -90
  332. package/template/.aioson/locales/fr/agents/product.md +0 -372
  333. package/template/.aioson/locales/fr/agents/profiler-enricher.md +0 -7
  334. package/template/.aioson/locales/fr/agents/profiler-forge.md +0 -7
  335. package/template/.aioson/locales/fr/agents/profiler-researcher.md +0 -7
  336. package/template/.aioson/locales/fr/agents/qa.md +0 -198
  337. package/template/.aioson/locales/fr/agents/setup.md +0 -405
  338. package/template/.aioson/locales/fr/agents/sheldon.md +0 -309
  339. package/template/.aioson/locales/fr/agents/squad.md +0 -532
  340. package/template/.aioson/locales/fr/agents/tester.md +0 -9
  341. package/template/.aioson/locales/fr/agents/ux-ui.md +0 -212
  342. package/template/.aioson/locales/pt-BR/agents/analyst.md +0 -319
  343. package/template/.aioson/locales/pt-BR/agents/architect.md +0 -284
  344. package/template/.aioson/locales/pt-BR/agents/dev.md +0 -483
  345. package/template/.aioson/locales/pt-BR/agents/deyvin.md +0 -184
  346. package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +0 -198
  347. package/template/.aioson/locales/pt-BR/agents/genome.md +0 -297
  348. package/template/.aioson/locales/pt-BR/agents/neo.md +0 -208
  349. package/template/.aioson/locales/pt-BR/agents/orache.md +0 -137
  350. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +0 -324
  351. package/template/.aioson/locales/pt-BR/agents/pair.md +0 -5
  352. package/template/.aioson/locales/pt-BR/agents/pm.md +0 -182
  353. package/template/.aioson/locales/pt-BR/agents/product.md +0 -466
  354. package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +0 -5
  355. package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +0 -5
  356. package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +0 -5
  357. package/template/.aioson/locales/pt-BR/agents/qa.md +0 -300
  358. package/template/.aioson/locales/pt-BR/agents/setup.md +0 -533
  359. package/template/.aioson/locales/pt-BR/agents/sheldon.md +0 -323
  360. package/template/.aioson/locales/pt-BR/agents/squad.md +0 -1330
  361. package/template/.aioson/locales/pt-BR/agents/tester.md +0 -449
  362. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +0 -669
@@ -18,6 +18,8 @@ const {
18
18
  } = require('../runtime-store');
19
19
  const { ensureDir, exists } = require('../utils');
20
20
  const { SUPPORTED_PROMPT_TOOLS } = require('../prompt-tool');
21
+ const { isTmuxAvailable, launchTmuxSession, buildSessionName, hasSession, attachSession } = require('../lib/tmux-launcher');
22
+ const { resolveResumeArgs } = require('../lib/tool-capabilities');
21
23
 
22
24
  const LIVE_EVENTS_LIMIT = 10;
23
25
  const LIVE_MESSAGE_LIMIT = 500;
@@ -99,6 +101,15 @@ function parseJsonOption(value) {
99
101
  }
100
102
  }
101
103
 
104
+ // Combine `--resume` (mapped per-tool via TOOL_CAPS) with user-provided `--tool-args`.
105
+ // Resume args go FIRST so that codex `resume --last` (subcommand) lands at argv[1].
106
+ function buildLaunchArgs(options, tool) {
107
+ const resumeOpt = options.resume !== undefined ? options.resume : options.Resume;
108
+ const resumeArgs = resolveResumeArgs(tool, resumeOpt);
109
+ const userArgs = parseToolArgs(options['tool-args'] || options.toolArgs);
110
+ return [...resumeArgs, ...userArgs];
111
+ }
112
+
102
113
  function parseToolArgs(value) {
103
114
  if (value === undefined || value === null || value === '') return [];
104
115
  if (Array.isArray(value)) return value.map((entry) => String(entry));
@@ -732,6 +743,245 @@ function renderLiveSummary(snapshot) {
732
743
  return lines.join('\n');
733
744
  }
734
745
 
746
+ // ANSI color helpers (no external deps)
747
+ const ANSI = {
748
+ reset: '\x1b[0m',
749
+ bold: '\x1b[1m',
750
+ dim: '\x1b[2m',
751
+ green: '\x1b[32m',
752
+ yellow: '\x1b[33m',
753
+ red: '\x1b[31m',
754
+ cyan: '\x1b[36m',
755
+ magenta: '\x1b[35m',
756
+ blue: '\x1b[34m',
757
+ gray: '\x1b[90m'
758
+ };
759
+
760
+ function colorForContext(pct) {
761
+ if (pct >= 90) return ANSI.red;
762
+ if (pct >= 70) return ANSI.yellow;
763
+ return ANSI.green;
764
+ }
765
+
766
+ function colorForPhase(phase) {
767
+ if (phase === 'active') return ANSI.green;
768
+ if (phase === 'closed') return ANSI.gray;
769
+ return ANSI.yellow;
770
+ }
771
+
772
+ function colorForProcess(state) {
773
+ if (state === 'alive') return ANSI.green;
774
+ if (state === 'dead') return ANSI.red;
775
+ return ANSI.gray;
776
+ }
777
+
778
+ function formatDurationCompact(startedAt) {
779
+ if (!startedAt) return '';
780
+ const ms = Date.now() - Date.parse(startedAt);
781
+ if (!Number.isFinite(ms) || ms < 0) return '';
782
+ const m = Math.floor(ms / 60000);
783
+ const s = Math.floor((ms % 60000) / 1000);
784
+ if (m > 60) {
785
+ const h = Math.floor(m / 60);
786
+ return `${h}h${m % 60}m`;
787
+ }
788
+ return `${m}m${s}s`;
789
+ }
790
+
791
+ /**
792
+ * Print a one-line compact status bar with ANSI colors.
793
+ * Designed for small tmux panes (~4 lines).
794
+ */
795
+ function printCompactStatus(snapshot, logger) {
796
+ const agent = snapshot.agent || '-';
797
+ const tool = snapshot.tool || '-';
798
+ const phase = snapshot.phase || 'idle';
799
+ const proc = snapshot.processState || 'not_tracked';
800
+ const pid = snapshot.pid || null;
801
+
802
+ // Context percentage if available
803
+ let ctxStr = '';
804
+ if (snapshot.run && snapshot.run.context_pct != null) {
805
+ const pct = Number(snapshot.run.context_pct) || 0;
806
+ ctxStr = `${colorForContext(pct)}ctx:${pct}%${ANSI.reset}`;
807
+ }
808
+
809
+ // Token / cost if available
810
+ let costStr = '';
811
+ if (snapshot.stats && snapshot.stats.tokens_total) {
812
+ const tokens = snapshot.stats.tokens_total;
813
+ const cost = snapshot.stats.cost_usd;
814
+ costStr = `${ANSI.cyan}${tokens >= 1000 ? (tokens / 1000).toFixed(1) + 'k' : tokens}tk${ANSI.reset}`;
815
+ if (cost != null) {
816
+ costStr += `${ANSI.gray}/${ANSI.reset}${ANSI.cyan}$${cost.toFixed(3)}${ANSI.reset}`;
817
+ }
818
+ }
819
+
820
+ // Plan progress
821
+ let planStr = '';
822
+ const planDone = snapshot.stats?.plan_steps_done ?? 0;
823
+ const planTotal = snapshot.stats?.plan_steps_total ?? 0;
824
+ if (planTotal > 0) {
825
+ planStr = `${ANSI.magenta}plan:${planDone}/${planTotal}${ANSI.reset}`;
826
+ }
827
+
828
+ // Duration
829
+ const dur = formatDurationCompact(snapshot.startedAt);
830
+ const durStr = dur ? `${ANSI.blue}${dur}${ANSI.reset}` : '';
831
+
832
+ // Recent event
833
+ let eventStr = '';
834
+ if (snapshot.recentEvents && snapshot.recentEvents.length > 0) {
835
+ const ev = snapshot.recentEvents[snapshot.recentEvents.length - 1];
836
+ eventStr = `${ANSI.gray}${ev.type}${ANSI.reset}`;
837
+ if (ev.summary) {
838
+ const short = String(ev.summary).slice(0, 35);
839
+ eventStr += `:${ANSI.gray}${short}${ANSI.reset}`;
840
+ }
841
+ }
842
+
843
+ // Warning
844
+ let warnStr = '';
845
+ if (snapshot.warning) {
846
+ warnStr = `${ANSI.red}⚠ ${snapshot.warning}${ANSI.reset}`;
847
+ }
848
+
849
+ // Build line 1
850
+ const parts = [
851
+ `${colorForPhase(phase)}●${ANSI.reset}`,
852
+ `${ANSI.bold}${agent}${ANSI.reset}`,
853
+ `|`,
854
+ `${ANSI.blue}${tool}${ANSI.reset}`,
855
+ `|`,
856
+ `${colorForProcess(proc)}${proc}${ANSI.reset}`,
857
+ pid ? `${ANSI.gray}(pid:${pid})${ANSI.reset}` : '',
858
+ ctxStr,
859
+ costStr,
860
+ planStr,
861
+ durStr,
862
+ eventStr,
863
+ warnStr
864
+ ].filter(Boolean);
865
+
866
+ logger.log(parts.join(' '));
867
+ }
868
+
869
+ /**
870
+ * Print two plain-text lines optimized for tmux status-bar.
871
+ * No ANSI colors — tmux handles its own styling.
872
+ * Designed for a 2-line pane.
873
+ */
874
+ function renderMiniBar(pct, width = 10, usedLabel = '', totalLabel = '') {
875
+ const filled = Math.round((pct / 100) * width);
876
+ const empty = width - filled;
877
+ const bar = '█'.repeat(filled) + '░'.repeat(empty);
878
+ const color = pct > 80 ? '\x1b[31m' : pct > 50 ? '\x1b[33m' : '\x1b[32m';
879
+ const reset = '\x1b[0m';
880
+ const abs = usedLabel && totalLabel ? ` ${usedLabel}/${totalLabel}` : '';
881
+ return `${color}[${bar}]${reset}${abs} ${pct}%`;
882
+ }
883
+
884
+ function formatProjectPath(targetDir) {
885
+ if (!targetDir) return '-';
886
+ const home = process.env.HOME || process.env.USERPROFILE || '';
887
+ let path = String(targetDir).replace(/\\/g, '/');
888
+ if (home && path.startsWith(home.replace(/\\/g, '/'))) {
889
+ path = '~' + path.slice(home.length);
890
+ }
891
+ if (path.length <= 28) return path;
892
+ // Too long: keep last 2 segments with ellipsis
893
+ const segments = path.split('/').filter(Boolean);
894
+ if (segments.length <= 2) return path;
895
+ const lastTwo = segments.slice(-2).join('/');
896
+ return `~/.../${lastTwo}`;
897
+ }
898
+
899
+ function printTmuxBar(snapshot) {
900
+ const agent = snapshot.agent || '-';
901
+ const tool = snapshot.tool || '-';
902
+ const phase = snapshot.phase || 'idle';
903
+ const projectDir = formatProjectPath(snapshot.targetDir);
904
+ const dur = formatDurationCompact(snapshot.startedAt);
905
+
906
+ // Build core info
907
+ const parts = [];
908
+ parts.push(`\x1b[1;36m${projectDir}\x1b[0m`);
909
+ parts.push(`\x1b[1;35m${agent}\x1b[0m`);
910
+ parts.push(`\x1b[90m${tool}\x1b[0m`);
911
+
912
+ if (phase === 'active') {
913
+ parts.push(`\x1b[32m●\x1b[0m`);
914
+ } else if (phase === 'closed') {
915
+ parts.push(`\x1b[31m○\x1b[0m`);
916
+ } else {
917
+ parts.push(`\x1b[33m${phase}\x1b[0m`);
918
+ }
919
+
920
+ if (dur) {
921
+ parts.push(dur);
922
+ }
923
+
924
+ // Plan progress
925
+ const planDone = snapshot.stats?.plan_steps_done ?? 0;
926
+ const planTotal = snapshot.stats?.plan_steps_total ?? 0;
927
+ if (planTotal > 0) {
928
+ parts.push(`step ${planDone}/${planTotal}`);
929
+ }
930
+
931
+ // Context bar with absolute numbers
932
+ if (snapshot.run && snapshot.run.context_pct != null) {
933
+ const pct = Number(snapshot.run.context_pct) || 0;
934
+ parts.push(`ctx ${renderMiniBar(pct)}`);
935
+ } else if (snapshot.contextEstimated) {
936
+ const est = snapshot.contextEstimated;
937
+ const pct = est.pct ?? 0;
938
+ const used = est.estimatedTokens >= 1000 ? (est.estimatedTokens / 1000).toFixed(1) + 'k' : String(est.estimatedTokens);
939
+ const total = est.windowSize >= 1000 ? (est.windowSize / 1000).toFixed(1) + 'k' : String(est.windowSize);
940
+ parts.push(`ctx ${renderMiniBar(pct, 10, used, total)}`);
941
+ }
942
+
943
+ // Cost
944
+ if (snapshot.stats && snapshot.stats.tokens_total) {
945
+ const tokens = snapshot.stats.tokens_total;
946
+ const cost = snapshot.stats.cost_usd;
947
+ const tk = tokens >= 1000 ? (tokens / 1000).toFixed(1) + 'k' : tokens;
948
+ if (cost != null) {
949
+ parts.push(`$${cost.toFixed(2)} (${tk}tk)`);
950
+ } else {
951
+ parts.push(`${tk}tk`);
952
+ }
953
+ }
954
+
955
+ // Recent useful event (skip session_started boilerplate)
956
+ let lastEvent = null;
957
+ if (snapshot.recentEvents && snapshot.recentEvents.length > 0) {
958
+ for (let i = snapshot.recentEvents.length - 1; i >= 0; i--) {
959
+ const ev = snapshot.recentEvents[i];
960
+ const type = String(ev.type || '');
961
+ if (type !== 'session_started' && type !== 'session_closed') {
962
+ lastEvent = ev;
963
+ break;
964
+ }
965
+ }
966
+ }
967
+ if (lastEvent) {
968
+ const short = String(lastEvent.summary || lastEvent.type || '').slice(0, 40);
969
+ if (short) {
970
+ parts.push(`\x1b[90m${short}\x1b[0m`);
971
+ }
972
+ }
973
+
974
+ // Warning
975
+ if (snapshot.warning) {
976
+ parts.push(`\x1b[1;31m! ${snapshot.warning}\x1b[0m`);
977
+ }
978
+
979
+ // When running inside the tmux updater, omit newline so the line can be overwritten.
980
+ // When called directly by a user, append newline for clean shell prompt.
981
+ const suffix = process.env.AIOSON_TMUX_BAR ? '' : '\n';
982
+ process.stdout.write(parts.join(' │ ') + suffix);
983
+ }
984
+
735
985
  function printLiveStatusSnapshot(snapshot, logger) {
736
986
  logger.log(`Live session: ${snapshot.sessionKey || 'none'}`);
737
987
  logger.log(`Phase: ${snapshot.phase}`);
@@ -819,11 +1069,17 @@ async function getLiveStatusSnapshot(targetDir, t, options = {}) {
819
1069
  });
820
1070
  state.stats = normalizeLiveStats(state.stats, planStats);
821
1071
 
1072
+ // Prefer run.agent_name when no explicit --agent was passed;
1073
+ // this lets events emitted by other agents update the bar dynamically.
1074
+ const effectiveAgent = options.agent
1075
+ ? context.agentName
1076
+ : (context.run?.agent_name || context.agentName);
1077
+
822
1078
  const snapshot = {
823
1079
  ok: true,
824
1080
  targetDir,
825
1081
  dbPath,
826
- agent: context.agentName,
1082
+ agent: effectiveAgent,
827
1083
  tool: state.tool_session || null,
828
1084
  phase: context.phase,
829
1085
  open: context.open,
@@ -839,11 +1095,21 @@ async function getLiveStatusSnapshot(targetDir, t, options = {}) {
839
1095
  task: context.task,
840
1096
  stats: state.stats,
841
1097
  recentEvents: Array.isArray(state.last_events) && state.last_events.length > 0 ? state.last_events : context.recentEvents,
1098
+ contextEstimated: state.context_estimated || null,
842
1099
  warning: context.processState === 'dead' && context.phase === 'active'
843
1100
  ? t('live.process_dead_warning')
844
1101
  : null
845
1102
  };
846
1103
 
1104
+ // Fallback: estimate context on-the-fly if not recorded at session start
1105
+ if (!snapshot.contextEstimated && snapshot.phase !== 'idle') {
1106
+ try {
1107
+ snapshot.contextEstimated = await estimateContextSize(targetDir);
1108
+ } catch {
1109
+ // non-fatal
1110
+ }
1111
+ }
1112
+
847
1113
  return snapshot;
848
1114
  } finally {
849
1115
  db.close();
@@ -880,6 +1146,16 @@ async function runLiveStart({ args, options = {}, logger, t }) {
880
1146
  throw new Error(t('live.tool_binary_not_found', { binary: toolBinary }));
881
1147
  }
882
1148
 
1149
+ const useTmux = Boolean(options.tmux) || process.env.AIOSON_TMUX === '1';
1150
+
1151
+ // Pre-check tmux availability so we can warn early
1152
+ if (useTmux && !noLaunch) {
1153
+ const tmuxOk = await isTmuxAvailable();
1154
+ if (!tmuxOk && !options.json) {
1155
+ logger.log(t('live.tmux_not_found', { tool }));
1156
+ }
1157
+ }
1158
+
883
1159
  const { db, dbPath, runtimeDir } = await openRuntimeDb(targetDir);
884
1160
 
885
1161
  try {
@@ -895,56 +1171,107 @@ async function runLiveStart({ args, options = {}, logger, t }) {
895
1171
  projectPath: targetDir
896
1172
  });
897
1173
 
898
- const existingTool = state.tool_session || null;
899
- if (existingTool && existingTool !== tool) {
900
- throw new Error(t('live.tool_mismatch', { existing: existingTool, requested: tool }));
901
- }
1174
+ // ── Tmux session recovery: if tmux was killed, close the stale live session ──
1175
+ if (useTmux) {
1176
+ const sessionName = buildSessionName(targetDir, agentName);
1177
+ const tmuxAlive = await hasSession(sessionName);
1178
+ if (!tmuxAlive) {
1179
+ // Tmux is gone — close the stale live session in DB and continue to create new
1180
+ const now = new Date().toISOString();
1181
+ updateRun(db, {
1182
+ runKey: existing.run.run_key,
1183
+ status: 'completed',
1184
+ summary: 'Closed because tmux session was terminated',
1185
+ eventType: 'session_closed',
1186
+ phase: 'live',
1187
+ message: 'Tmux session ended — live session auto-closed'
1188
+ });
1189
+ if (existing.task?.task_key) {
1190
+ updateTask(db, {
1191
+ taskKey: existing.task.task_key,
1192
+ status: 'completed',
1193
+ goal: 'Auto-closed after tmux termination'
1194
+ });
1195
+ }
1196
+ await clearAgentSession(runtimeDir, agentName);
1197
+ if (!options.json) {
1198
+ logger.log(t('live.tmux_recreate', { agent: agentName, session: existing.sessionKey }));
1199
+ }
1200
+ // Fall through to create a new session below
1201
+ } else {
1202
+ // Tmux still alive — reattach instead of creating new
1203
+ if (!options.json) {
1204
+ logger.log(t('live.tmux_reattach', { agent: agentName, session: existing.sessionKey }));
1205
+ }
1206
+ const sessionName = buildSessionName(targetDir, agentName);
1207
+ await attachSession(sessionName);
1208
+ return {
1209
+ ok: true,
1210
+ targetDir,
1211
+ dbPath,
1212
+ tmux: true,
1213
+ reused: true,
1214
+ agent: existing.agentName,
1215
+ tool: state.tool_session || tool,
1216
+ taskKey: existing.task?.task_key || existing.sessionRef?.taskKey || null,
1217
+ runKey: existing.run.run_key,
1218
+ sessionKey: existing.sessionKey,
1219
+ open: true
1220
+ };
1221
+ }
1222
+ } else {
1223
+ // Non-tmux reuse logic (original behavior)
1224
+ const existingTool = state.tool_session || null;
1225
+ if (existingTool && existingTool !== tool) {
1226
+ throw new Error(t('live.tool_mismatch', { existing: existingTool, requested: tool }));
1227
+ }
902
1228
 
903
- const attach = Boolean(options.attach);
904
- let attachChild = null;
905
- let attachResult = null;
1229
+ const attach = Boolean(options.attach);
1230
+ let attachChild = null;
1231
+ let attachResult = null;
906
1232
 
907
- if (attach && !noLaunch) {
908
- attachChild = spawn(binaryPath, parseToolArgs(options['tool-args'] || options.toolArgs), {
909
- cwd: targetDir,
910
- env: process.env,
911
- stdio: 'inherit'
912
- });
913
- state.child_pid = attachChild.pid || null;
914
- if (existing.task?.task_key) {
915
- const taskMeta = parseTaskMeta(existing.task);
916
- taskMeta.child_pid = state.child_pid;
917
- updateTask(db, { taskKey: existing.task.task_key, metaJson: taskMeta });
1233
+ if (attach && !noLaunch) {
1234
+ attachChild = spawn(binaryPath, buildLaunchArgs(options, tool), {
1235
+ cwd: targetDir,
1236
+ env: process.env,
1237
+ stdio: 'inherit'
1238
+ });
1239
+ state.child_pid = attachChild.pid || null;
1240
+ if (existing.task?.task_key) {
1241
+ const taskMeta = parseTaskMeta(existing.task);
1242
+ taskMeta.child_pid = state.child_pid;
1243
+ updateTask(db, { taskKey: existing.task.task_key, metaJson: taskMeta });
1244
+ }
918
1245
  }
919
- }
920
1246
 
921
- await writeLiveState(runtimeDir, existing.sessionKey, state);
1247
+ await writeLiveState(runtimeDir, existing.sessionKey, state);
922
1248
 
923
- if (!options.json) {
924
- logger.log(t('live.session_already_active', { agent: agentName, session: existing.sessionKey, runKey: existing.run.run_key, dbPath }));
925
- }
1249
+ if (!options.json) {
1250
+ logger.log(t('live.session_already_active', { agent: agentName, session: existing.sessionKey, runKey: existing.run.run_key, dbPath }));
1251
+ }
926
1252
 
927
- if (attachChild) {
928
- attachResult = await waitForChild(attachChild);
929
- }
1253
+ if (attachChild) {
1254
+ attachResult = await waitForChild(attachChild);
1255
+ }
930
1256
 
931
- return {
932
- ok: true,
933
- targetDir,
934
- dbPath,
935
- agent: existing.agentName,
936
- tool: state.tool_session || tool,
937
- taskKey: existing.task?.task_key || existing.sessionRef?.taskKey || null,
938
- runKey: existing.run.run_key,
939
- sessionKey: existing.sessionKey,
940
- pid: state.child_pid || null,
941
- processState: detectProcessState(state.child_pid),
942
- reused: true,
943
- open: true,
944
- attached: attach,
945
- childExitCode: attachResult?.code ?? null,
946
- childSignal: attachResult?.signal ?? null
947
- };
1257
+ return {
1258
+ ok: true,
1259
+ targetDir,
1260
+ dbPath,
1261
+ agent: existing.agentName,
1262
+ tool: state.tool_session || tool,
1263
+ taskKey: existing.task?.task_key || existing.sessionRef?.taskKey || null,
1264
+ runKey: existing.run.run_key,
1265
+ sessionKey: existing.sessionKey,
1266
+ pid: state.child_pid || null,
1267
+ processState: detectProcessState(state.child_pid),
1268
+ reused: true,
1269
+ open: true,
1270
+ attached: attach,
1271
+ childExitCode: attachResult?.code ?? null,
1272
+ childSignal: attachResult?.signal ?? null
1273
+ };
1274
+ }
948
1275
  }
949
1276
 
950
1277
  const now = new Date().toISOString();
@@ -994,17 +1321,46 @@ async function runLiveStart({ args, options = {}, logger, t }) {
994
1321
 
995
1322
  let child = null;
996
1323
  let childResult = null;
1324
+ let tmuxResult = null;
997
1325
  if (!noLaunch) {
998
- child = spawn(binaryPath, parseToolArgs(options['tool-args'] || options.toolArgs), {
999
- cwd: targetDir,
1000
- env: process.env,
1001
- stdio: 'inherit'
1002
- });
1003
- taskMeta.child_pid = child.pid || null;
1004
- updateTask(db, {
1005
- taskKey,
1006
- metaJson: taskMeta
1007
- });
1326
+ if (useTmux) {
1327
+ const tmuxOk = await isTmuxAvailable();
1328
+ if (tmuxOk) {
1329
+ if (!options.json) {
1330
+ logger.log(t('live.tmux_starting', { agent: agentName, tool }));
1331
+ }
1332
+ tmuxResult = await launchTmuxSession({
1333
+ targetDir,
1334
+ agentName,
1335
+ tool,
1336
+ binaryPath,
1337
+ toolArgs: buildLaunchArgs(options, tool)
1338
+ });
1339
+ } else {
1340
+ // Fallback to normal spawn if tmux not available
1341
+ child = spawn(binaryPath, buildLaunchArgs(options, tool), {
1342
+ cwd: targetDir,
1343
+ env: process.env,
1344
+ stdio: 'inherit'
1345
+ });
1346
+ taskMeta.child_pid = child.pid || null;
1347
+ updateTask(db, {
1348
+ taskKey,
1349
+ metaJson: taskMeta
1350
+ });
1351
+ }
1352
+ } else {
1353
+ child = spawn(binaryPath, buildLaunchArgs(options, tool), {
1354
+ cwd: targetDir,
1355
+ env: process.env,
1356
+ stdio: 'inherit'
1357
+ });
1358
+ taskMeta.child_pid = child.pid || null;
1359
+ updateTask(db, {
1360
+ taskKey,
1361
+ metaJson: taskMeta
1362
+ });
1363
+ }
1008
1364
  }
1009
1365
 
1010
1366
  await writeAgentSession(runtimeDir, agentName, {
@@ -1051,6 +1407,14 @@ async function runLiveStart({ args, options = {}, logger, t }) {
1051
1407
  }]
1052
1408
  });
1053
1409
 
1410
+ // Estimate context size for observability
1411
+ try {
1412
+ const ctxEst = await estimateContextSize(targetDir);
1413
+ state.context_estimated = ctxEst;
1414
+ } catch {
1415
+ // non-fatal
1416
+ }
1417
+
1054
1418
  await writeLiveState(runtimeDir, sessionKey, state);
1055
1419
  await appendLiveEvent(runtimeDir, sessionKey, {
1056
1420
  ts: now,
@@ -1097,6 +1461,25 @@ async function runLiveStart({ args, options = {}, logger, t }) {
1097
1461
  childResult = await waitForChild(child);
1098
1462
  }
1099
1463
 
1464
+ if (tmuxResult) {
1465
+ return {
1466
+ ok: true,
1467
+ targetDir,
1468
+ dbPath,
1469
+ tmux: true,
1470
+ sessionName: tmuxResult.sessionName,
1471
+ agent: agentName,
1472
+ tool,
1473
+ taskKey,
1474
+ runKey,
1475
+ sessionKey,
1476
+ pid: null,
1477
+ processState: 'tmux',
1478
+ reused: false,
1479
+ open: true
1480
+ };
1481
+ }
1482
+
1100
1483
  return {
1101
1484
  ok: true,
1102
1485
  targetDir,
@@ -1426,7 +1809,13 @@ async function runLiveStatus({ args, options = {}, logger, t }) {
1426
1809
  if (!watchSeconds) {
1427
1810
  const snapshot = await getLiveStatusSnapshot(targetDir, t, options);
1428
1811
  if (!options.json) {
1429
- printLiveStatusSnapshot(snapshot, logger);
1812
+ if (options.format === 'compact') {
1813
+ printCompactStatus(snapshot, logger);
1814
+ } else if (options.format === 'tmux-bar') {
1815
+ printTmuxBar(snapshot, logger);
1816
+ } else {
1817
+ printLiveStatusSnapshot(snapshot, logger);
1818
+ }
1430
1819
  }
1431
1820
  return snapshot;
1432
1821
  }
@@ -1442,7 +1831,13 @@ async function runLiveStatus({ args, options = {}, logger, t }) {
1442
1831
  if (process.stdout && process.stdout.isTTY) {
1443
1832
  process.stdout.write('\x1Bc');
1444
1833
  }
1445
- printLiveStatusSnapshot(snapshot, logger);
1834
+ if (options.format === 'compact') {
1835
+ printCompactStatus(snapshot, logger);
1836
+ } else if (options.format === 'tmux-bar') {
1837
+ printTmuxBar(snapshot, logger);
1838
+ } else {
1839
+ printLiveStatusSnapshot(snapshot, logger);
1840
+ }
1446
1841
  if (stopped) break;
1447
1842
  await sleep(Math.round(watchSeconds * 1000));
1448
1843
  }
@@ -1632,6 +2027,7 @@ async function runLiveList({ args, options = {}, logger, t }) {
1632
2027
  }
1633
2028
 
1634
2029
  module.exports = {
2030
+ buildLaunchArgs,
1635
2031
  runLiveStart,
1636
2032
  runRuntimeEmit,
1637
2033
  runLiveHandoff,
@@ -1639,3 +2035,48 @@ module.exports = {
1639
2035
  runLiveClose,
1640
2036
  runLiveList
1641
2037
  };
2038
+
2039
+ // ── Context estimation helpers ──
2040
+
2041
+ const CONTEXT_FILES = [
2042
+ '.aioson/context/project.context.md',
2043
+ '.aioson/context/spec.md',
2044
+ '.aioson/context/features.md',
2045
+ '.aioson/context/context-pack.md',
2046
+ '.aioson/context/discovery.md',
2047
+ '.aioson/context/architecture.md',
2048
+ '.aioson/context/readiness.md',
2049
+ '.aioson/context/design-doc.md',
2050
+ '.aioson/context/skeleton-system.md'
2051
+ ];
2052
+
2053
+ async function estimateContextSize(projectDir) {
2054
+ let totalBytes = 0;
2055
+ const foundFiles = [];
2056
+
2057
+ for (const rel of CONTEXT_FILES) {
2058
+ const filePath = path.join(projectDir, rel);
2059
+ try {
2060
+ const stat = await fs.stat(filePath);
2061
+ if (stat.isFile()) {
2062
+ totalBytes += stat.size;
2063
+ foundFiles.push(rel);
2064
+ }
2065
+ } catch {
2066
+ // ignore missing files
2067
+ }
2068
+ }
2069
+
2070
+ // Heuristic: ~4 chars per token (english-ish text)
2071
+ const estimatedTokens = Math.round(totalBytes / 4);
2072
+ // Default window size assumption (200k for Sonnet-class)
2073
+ const windowSize = 200000;
2074
+
2075
+ return {
2076
+ totalBytes,
2077
+ estimatedTokens,
2078
+ windowSize,
2079
+ pct: Math.min(100, Math.round((estimatedTokens / windowSize) * 100)),
2080
+ files: foundFiles
2081
+ };
2082
+ }
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('node:path');
4
- const { applyAgentLocale, resolveAgentLocale } = require('../locales');
5
- const { validateProjectContextFile } = require('../context');
4
+ const { applyAgentLocale, normalizeInteractionLanguage } = require('../locales');
5
+ const { validateProjectContextFile, getInteractionLanguage } = require('../context');
6
6
 
7
7
  async function runLocaleApply({ args, options, logger, t }) {
8
8
  const targetDir = path.resolve(process.cwd(), args[0] || '.');
@@ -11,13 +11,16 @@ async function runLocaleApply({ args, options, logger, t }) {
11
11
  let requestedLanguage = options.language || options.lang || '';
12
12
  if (!requestedLanguage) {
13
13
  const context = await validateProjectContextFile(targetDir);
14
- if (context.parsed && context.data && context.data.conversation_language) {
15
- requestedLanguage = context.data.conversation_language;
14
+ if (context.parsed && context.data) {
15
+ requestedLanguage = getInteractionLanguage(context.data, 'en');
16
16
  }
17
17
  }
18
18
 
19
- const locale = resolveAgentLocale(requestedLanguage || 'en');
20
- const result = await applyAgentLocale(targetDir, locale, { dryRun });
19
+ const result = await applyAgentLocale(
20
+ targetDir,
21
+ normalizeInteractionLanguage(requestedLanguage || 'en'),
22
+ { dryRun }
23
+ );
21
24
 
22
25
  logger.log(
23
26
  dryRun