@zaip-ai/cli 4.5.0 → 4.6.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 (211) hide show
  1. package/README.md +2 -0
  2. package/dist/services/adapters.d.ts +1 -1
  3. package/dist/services/adapters.js +4 -4
  4. package/dist/services/adapters.js.map +1 -1
  5. package/dist/services/codex-native-tool-authority-template.d.ts.map +1 -1
  6. package/dist/services/codex-native-tool-authority-template.js +188 -9
  7. package/dist/services/codex-native-tool-authority-template.js.map +1 -1
  8. package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
  9. package/dist/services/codex-pre-tool-hook-template.js +50 -128
  10. package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
  11. package/dist/services/codex-pre-tool-hook-template.test.js +4 -0
  12. package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -1
  13. package/dist/services/codex-pre-tool-support-template.d.ts.map +1 -1
  14. package/dist/services/codex-pre-tool-support-template.js +1 -4
  15. package/dist/services/codex-pre-tool-support-template.js.map +1 -1
  16. package/dist/services/codex-stale-git-lock-template.d.ts +2 -0
  17. package/dist/services/codex-stale-git-lock-template.d.ts.map +1 -0
  18. package/dist/services/codex-stale-git-lock-template.js +64 -0
  19. package/dist/services/codex-stale-git-lock-template.js.map +1 -0
  20. package/dist/services/global-codex-config-migration.test.js +1 -4
  21. package/dist/services/global-codex-config-migration.test.js.map +1 -1
  22. package/dist/services/install-template-policy.d.ts.map +1 -1
  23. package/dist/services/install-template-policy.js +2 -0
  24. package/dist/services/install-template-policy.js.map +1 -1
  25. package/dist/services/logger.js +2 -1
  26. package/dist/services/logger.js.map +1 -1
  27. package/dist/services/logger.test.js +71 -0
  28. package/dist/services/logger.test.js.map +1 -1
  29. package/dist/services/runtime-template-test-support.d.ts +3 -0
  30. package/dist/services/runtime-template-test-support.d.ts.map +1 -0
  31. package/dist/services/runtime-template-test-support.js +32 -0
  32. package/dist/services/runtime-template-test-support.js.map +1 -0
  33. package/dist/services/runtime-template.test.js +23 -31
  34. package/dist/services/runtime-template.test.js.map +1 -1
  35. package/package.json +1 -1
  36. package/templates/.agents/README.md +8 -0
  37. package/templates/.agents/config/agents/discovery.json +1 -1
  38. package/templates/.agents/config/deploy-policy.json +5 -0
  39. package/templates/.agents/dashboard/.zaip-managed.json +211 -75
  40. package/templates/.agents/dashboard/README.md +2 -0
  41. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-f4ZGJRg3.js → CostCalculationGuidePage-BRtiPijr.js} +1 -1
  42. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-CkQ_y8kg.js → DashboardHelpDialog-BR4ZeYpE.js} +99 -10
  43. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-v9zGRTlk.js → PricingSettingsDialog-Dr4QDFmn.js} +1 -1
  44. package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-doIMhei7.js → ProjectSettingsPage-BG0N5dw_.js} +1 -1
  45. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-C_4ftjyB.js → TraceabilityWorkspace-BvoM-YQ0.js} +1 -1
  46. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-fTQhSL85.js +68 -0
  47. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-Cv3WBFIF.js → icons-vendor-Bc6vux5t.js} +1 -1
  48. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-BMfzKaAR.js +2 -0
  49. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DZhppOIk.css +1 -0
  50. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-mHgsmxb6.js → react-vendor-DNJQFov3.js} +1 -1
  51. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-B0CPyEVq.js → traceability-B7tjIB7W.js} +1 -1
  52. package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
  53. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  54. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +6 -34
  55. package/templates/.agents/dashboard/apps/frontend/src/ReconciliationFeedback.dom.test.ts +130 -0
  56. package/templates/.agents/dashboard/apps/frontend/src/ReconciliationFeedback.tsx +226 -0
  57. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-sqlite-view.ts +45 -0
  58. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +15 -0
  59. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +17 -46
  60. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback-fixtures.ts +23 -0
  61. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback-model.test.ts +69 -0
  62. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback-model.ts +59 -0
  63. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback.css +131 -0
  64. package/templates/.agents/dashboard/apps/frontend/src/styles.css +0 -32
  65. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +2 -2
  66. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  67. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +2 -2
  68. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +1 -1
  69. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  70. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +1 -4
  71. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.navigation.test.ts +236 -0
  72. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +1 -24
  73. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +3 -2
  74. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  75. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  76. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  77. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  78. package/templates/.agents/dashboard/packages/local-runtime/DIAGNOSTICS.md +42 -0
  79. package/templates/.agents/dashboard/packages/local-runtime/dashboard-diagnostics.d.mts +10 -0
  80. package/templates/.agents/dashboard/packages/local-runtime/dashboard-diagnostics.mjs +101 -0
  81. package/templates/.agents/dashboard/packages/local-runtime/dashboard-diagnostics.test.mjs +58 -0
  82. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +232 -217
  83. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +201 -188
  84. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  85. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-dashboard-startup.mjs +233 -0
  86. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-provider-nonzero.mjs +45 -0
  87. package/templates/.agents/dashboard/packages/local-runtime/scripts/verify-dashboard-executable-startup.mjs +107 -0
  88. package/templates/.agents/dashboard/packages/local-runtime/scripts/verify-dashboard-reconciliation-executable.mjs +271 -0
  89. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +232 -217
  90. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.test.ts +78 -12
  91. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +36 -56
  92. package/templates/.agents/dashboard/packages/local-runtime/src/canonical-source-revision-cache.test.ts +125 -0
  93. package/templates/.agents/dashboard/packages/local-runtime/src/canonical-source-revision-cache.ts +168 -0
  94. package/templates/.agents/dashboard/packages/local-runtime/src/dashboard-diagnostics.test.ts +57 -0
  95. package/templates/.agents/dashboard/packages/local-runtime/src/server-agent-catalog-routes.ts +76 -0
  96. package/templates/.agents/dashboard/packages/local-runtime/src/server-dual-reads-manifest-summaries-without-losing.test.ts +5 -0
  97. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-diagnostics.test.ts +118 -0
  98. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-result.test.ts +35 -6
  99. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-route.ts +105 -0
  100. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +64 -9
  101. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +19 -27
  102. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-command.test.ts +111 -0
  103. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-refresh.test.ts +59 -0
  104. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-refresh.ts +44 -0
  105. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +20 -0
  106. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +12 -7
  107. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +48 -6
  108. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +2 -2
  109. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +126 -134
  110. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +14 -2
  111. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-dashboard-startup.test.ts +163 -0
  112. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-dashboard-startup.ts +78 -0
  113. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-header-timestamp.test.ts +31 -0
  114. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-provider-nonzero.test.ts +271 -0
  115. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-provider-visibility.ts +32 -0
  116. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-operations-duration.ts +58 -0
  117. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +12 -3
  118. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +9 -58
  119. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +9 -35
  120. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +10 -8
  121. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +43 -45
  122. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +5 -9
  123. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +5 -1
  124. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-startup-seed.test.ts +87 -0
  125. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-logging.mjs +6 -2
  126. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-server.mjs +7 -1
  127. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +4 -5
  128. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  129. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.test.mjs +33 -4
  130. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.tsx +8 -7
  131. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +46 -3
  132. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  133. package/templates/.agents/dashboard/tests/e2e/qualify-kanban-popup.mjs +56 -0
  134. package/templates/.agents/dashboard/tests/e2e/specs/dashboard-update-label.spec.ts +49 -0
  135. package/templates/.agents/design/.zaip-managed.json +17 -5
  136. package/templates/.agents/design/apps/catalog/dist/assets/index-D3uhpycC.js +72 -0
  137. package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
  138. package/templates/.agents/design/apps/catalog/package.json +1 -1
  139. package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +13 -1
  140. package/templates/.agents/design/apps/catalog/src/specimens/ReconciliationSpecimen.stories.tsx +6 -0
  141. package/templates/.agents/design/apps/catalog/src/specimens/ReconciliationSpecimen.tsx +101 -0
  142. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  143. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  144. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  145. package/templates/.agents/requirements/comparative-audit.md +1 -1
  146. package/templates/.agents/requirements/context-engine.md +1 -1
  147. package/templates/.agents/requirements/cost-observability.md +1 -1
  148. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  149. package/templates/.agents/requirements/data-export.md +1 -1
  150. package/templates/.agents/requirements/design-system.md +1 -1
  151. package/templates/.agents/requirements/execution-engine.md +1 -1
  152. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  153. package/templates/.agents/requirements/model-orchestration.md +21 -6
  154. package/templates/.agents/requirements/public-distribution.md +4 -4
  155. package/templates/.agents/requirements/software-architecture.md +1 -1
  156. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  157. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  158. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  159. package/templates/.agents/rules/core.md +3 -1
  160. package/templates/.agents/rules/workflow.md +3 -2
  161. package/templates/.agents/runtime/VERSION +1 -1
  162. package/templates/.agents/runtime/bin/zaip.mjs +366 -196
  163. package/templates/.agents/runtime/checksums.sha256 +5 -5
  164. package/templates/.agents/runtime/manifest.json +1 -1
  165. package/templates/.agents/runtime/provenance.json +4 -4
  166. package/templates/.agents/runtime/sbom.cdx.json +1 -1
  167. package/templates/.agents/skills/zaip-skill-config/SKILL.md +25 -3
  168. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +4 -0
  169. package/templates/.agents/skills/zaip-skill-execution/references/autonomous-continuation.md +4 -0
  170. package/templates/.agents/skills/zaip-skill-execution/references/candidate-workflow.md +1 -1
  171. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +2 -2
  172. package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +1 -0
  173. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +36 -48
  174. package/templates/.agents/skills/zaip-skill-github-deploy/agents/openai.yaml +2 -2
  175. package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +67 -99
  176. package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +33 -30
  177. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/deploy-contract.mjs +303 -0
  178. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/deploy-contract.test.mjs +334 -0
  179. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +41 -28
  180. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/guarded-commits.mjs +212 -0
  181. package/templates/.agents/skills/zaip-skill-lifecycle-closure/SKILL.md +4 -0
  182. package/templates/.agents/skills/zaip-skill-prd/SKILL.md +4 -0
  183. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +44 -68
  184. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +91 -44
  185. package/templates/.agents/skills/zaip-skill-send-email/SKILL.md +15 -0
  186. package/templates/.agents/skills/zaip-skill-send-email/agents/openai.yaml +4 -0
  187. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +5 -2
  188. package/templates/.agents/skills/zaip-skill-spec/SKILL.md +4 -0
  189. package/templates/.agents/skills/zaip-skill-task/SKILL.md +4 -0
  190. package/templates/.agents/skills/zaip-skill-testing-strategy/SKILL.md +19 -0
  191. package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +2 -0
  192. package/templates/.agents/skills/zaip-skill-use-connectors/SKILL.md +15 -0
  193. package/templates/.agents/skills/zaip-skill-use-connectors/agents/openai.yaml +4 -0
  194. package/templates/.agents/skills/zaip-skill-use-connectors/scripts/connector-guidance.test.mjs +29 -0
  195. package/templates/.agents/skills/zaip-skill-use-connectors/scripts/verify-connector-lock.mjs +30 -0
  196. package/templates/.agents/tools/cloud-runner.integration.test.mjs +3 -0
  197. package/templates/.agents/zaip-aios/VERSION +1 -1
  198. package/templates/.agents/zaip-aios/guides/03-tasks.md +6 -0
  199. package/templates/.agents/zaip-aios/guides/04-specs.md +6 -0
  200. package/templates/.agents/zaip-aios/guides/05-prds.md +4 -0
  201. package/templates/.agents/zaip-aios/guides/06-execucao.md +6 -0
  202. package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +6 -0
  203. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +4 -0
  204. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +6 -0
  205. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +36 -4
  206. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +15 -4
  207. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +8 -0
  208. package/templates/template-manifest.json +330 -142
  209. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-D7PrDZy9.js +0 -68
  210. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-OBJXZOwe.css +0 -1
  211. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Rbmpz4UO.js +0 -2
@@ -0,0 +1,101 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { appendFileSync, mkdirSync, readdirSync, renameSync, statSync, unlinkSync } from "node:fs";
3
+ import { join } from "node:path";
4
+
5
+ const secretKey =
6
+ /^(?:(?:access|refresh|session|ui|auth)[_-]?)?token$|authorization|cookie|password|secret|credential|api[_-]?key/i;
7
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI OSC sequences contain escape and bell controls.
8
+ const oscEscapePattern = /\x1b\][^\x07]*(?:\x07|\x1b\\)/g;
9
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI CSI sequences contain escape controls.
10
+ const csiEscapePattern = /\x1b\[[0-?]*[ -/]*[@-~]/g;
11
+ export function sanitizeDiagnostic(value, depth = 0) {
12
+ if (depth > 6) return "[depth limited]";
13
+ if (typeof value === "string") {
14
+ let text = value.replace(oscEscapePattern, "").replace(csiEscapePattern, "");
15
+ for (const secret of [process.env.ZAIP_UI_TOKEN, process.env.ZAIP_SESSION_TOKEN])
16
+ if (secret) text = text.replaceAll(secret, "[redacted]");
17
+ return text
18
+ .replace(/(Bearer\s+)[^\s"']+/gi, "$1[redacted]")
19
+ .replace(
20
+ /((?:token|authorization|cookie|password|secret|api[_-]?key)["']?\s*[:=]\s*["']?)[^\s"',};&]+/gi,
21
+ "$1[redacted]",
22
+ )
23
+ .replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/gi, "$1[redacted]@")
24
+ .slice(0, 16_000);
25
+ }
26
+ if (value instanceof Error) {
27
+ return sanitizeDiagnostic(
28
+ {
29
+ name: value.name,
30
+ message: value.message,
31
+ stack: value.stack,
32
+ ...Object.fromEntries(Object.entries(value)),
33
+ },
34
+ depth + 1,
35
+ );
36
+ }
37
+ if (Array.isArray(value))
38
+ return value.slice(0, 200).map((item) => sanitizeDiagnostic(item, depth + 1));
39
+ if (value && typeof value === "object")
40
+ return Object.fromEntries(
41
+ Object.entries(value)
42
+ .slice(0, 100)
43
+ .map(([key, item]) => [
44
+ key,
45
+ secretKey.test(key) ? "[redacted]" : sanitizeDiagnostic(item, depth + 1),
46
+ ]),
47
+ );
48
+ return typeof value === "bigint" ? String(value) : value;
49
+ }
50
+
51
+ export function createDashboardDiagnostics(workspaceRoot, component, options = {}) {
52
+ const inherited = process.env.ZAIP_DASHBOARD_LAUNCH_ID;
53
+ const correlationId = /^[a-zA-Z0-9-]{1,80}$/.test(inherited ?? "") ? inherited : randomUUID();
54
+ const directory = join(workspaceRoot, ".local", "dashboard-logs");
55
+ const path = join(directory, `${component}-${correlationId}-${process.pid}.jsonl`);
56
+ const maxBytes = options.maxBytes ?? 2 * 1024 * 1024;
57
+ let prepared = false;
58
+ let failed = false;
59
+ const log = (event, data = {}) => {
60
+ try {
61
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
62
+ if (!prepared) {
63
+ prepared = true;
64
+ const files = readdirSync(directory)
65
+ .filter((name) =>
66
+ /^(?:native|launcher|runtime|reconciliation)-[a-zA-Z0-9-]+\.jsonl(?:\.1)?$/.test(name),
67
+ )
68
+ .map((name) => ({ name, modified: statSync(join(directory, name)).mtimeMs }))
69
+ .sort((a, b) => b.modified - a.modified);
70
+ for (const [index, file] of files.entries())
71
+ if (index >= 60 || Date.now() - file.modified > 14 * 86400_000)
72
+ unlinkSync(join(directory, file.name));
73
+ }
74
+ if (statSync(path, { throwIfNoEntry: false })?.size >= maxBytes) {
75
+ const rotated = `${path}.1`;
76
+ if (statSync(rotated, { throwIfNoEntry: false })) unlinkSync(rotated);
77
+ renameSync(path, rotated);
78
+ }
79
+ appendFileSync(
80
+ path,
81
+ `${JSON.stringify({
82
+ ...sanitizeDiagnostic(data),
83
+ schema_version: 1,
84
+ occurred_at: new Date().toISOString(),
85
+ component,
86
+ event,
87
+ correlation_id: correlationId,
88
+ pid: process.pid,
89
+ })}\n`,
90
+ { encoding: "utf8", mode: 0o600 },
91
+ );
92
+ return true;
93
+ } catch {
94
+ if (!failed)
95
+ process.stderr.write("Dashboard diagnostic log unavailable in .local/dashboard-logs\n");
96
+ failed = true;
97
+ return false;
98
+ }
99
+ };
100
+ return { log, path, correlationId };
101
+ }
@@ -0,0 +1,58 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdir, mkdtemp, readdir, readFile, rm, utimes, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { test } from "node:test";
5
+ import { createDashboardDiagnostics, sanitizeDiagnostic } from "./dashboard-diagnostics.mjs";
6
+
7
+ test("persistent JSONL redacts credentials, bounds streams and preserves token collection time", async () => {
8
+ const base = new URL("../../../../.tmp/dashboard-diagnostic-tests/", import.meta.url);
9
+ await mkdir(base, { recursive: true });
10
+ const root = await mkdtemp(new URL("fixture-", base));
11
+ try {
12
+ const diagnostics = createDashboardDiagnostics(root, "reconciliation", { maxBytes: 400 });
13
+ const time = "2026-09-29T13:46:11.000Z";
14
+ assert.equal(
15
+ diagnostics.log("cli_error", {
16
+ job_id: "JOB-X",
17
+ latest_token_collected_at: time,
18
+ error: Object.assign(new Error("Bearer topsecret"), { stderr: "password=secret" }),
19
+ stdout: '{"access_token":"private"}',
20
+ cookie: "private",
21
+ }),
22
+ true,
23
+ );
24
+ const original = await readFile(diagnostics.path, "utf8");
25
+ const event = JSON.parse(original);
26
+ assert.equal(event.latest_token_collected_at, time);
27
+ assert.equal(event.job_id, "JOB-X");
28
+ assert.ok(event.occurred_at);
29
+ assert.equal(/topsecret|private|password=secret/.test(original), false);
30
+ diagnostics.log("next", { stdout: "x".repeat(20_000) });
31
+ assert.equal(JSON.parse(await readFile(diagnostics.path, "utf8")).stdout.length, 16_000);
32
+ assert.equal(await readFile(diagnostics.path + ".1", "utf8"), original);
33
+ assert.equal(sanitizeDiagnostic("\x1b[31mBearer secret\x1b[0m"), "Bearer [redacted]");
34
+ } finally {
35
+ await rm(root, { recursive: true, force: true });
36
+ }
37
+ });
38
+
39
+ test("retains recent owned logs and removes aged owned logs only", async () => {
40
+ const base = new URL("../../../../.tmp/dashboard-diagnostic-tests/", import.meta.url);
41
+ await mkdir(base, { recursive: true });
42
+ const root = await mkdtemp(new URL("fixture-", base));
43
+ try {
44
+ const directory = join(root, ".local", "dashboard-logs");
45
+ await mkdir(directory, { recursive: true });
46
+ await writeFile(join(directory, "runtime-old-123.jsonl"), "{}\n");
47
+ await writeFile(join(directory, "unrelated.jsonl"), "{}\n");
48
+ const old = new Date(Date.now() - 15 * 86400_000);
49
+ await utimes(join(directory, "runtime-old-123.jsonl"), old, old);
50
+ await utimes(join(directory, "unrelated.jsonl"), old, old);
51
+ assert.equal(createDashboardDiagnostics(root, "launcher").log("start"), true);
52
+ const files = await readdir(directory);
53
+ assert.equal(files.includes("runtime-old-123.jsonl"), false);
54
+ assert.equal(files.includes("unrelated.jsonl"), true);
55
+ } finally {
56
+ await rm(root, { recursive: true, force: true });
57
+ }
58
+ });