avorelo 0.1.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 (258) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/bin/avorelo +9 -0
  4. package/package.json +135 -0
  5. package/scripts/README.md +40 -0
  6. package/scripts/cco-dashboard.js +252 -0
  7. package/scripts/cco-status.js +430 -0
  8. package/scripts/lib/activation/account-state.js +37 -0
  9. package/scripts/lib/activation/activation-runner.js +546 -0
  10. package/scripts/lib/activation/activation-self-healing.js +480 -0
  11. package/scripts/lib/activation/activation-state.js +83 -0
  12. package/scripts/lib/activation/activation-summary.js +191 -0
  13. package/scripts/lib/activation/adapters/claude-code.js +77 -0
  14. package/scripts/lib/activation/adapters/codex-cli.js +52 -0
  15. package/scripts/lib/activation/adapters/cursor.js +37 -0
  16. package/scripts/lib/activation/adapters/github-agent.js +39 -0
  17. package/scripts/lib/activation/adapters/terminal.js +42 -0
  18. package/scripts/lib/activation/adapters/vscode.js +39 -0
  19. package/scripts/lib/activation/adapters/windsurf.js +37 -0
  20. package/scripts/lib/activation/ai-surface-detector.js +151 -0
  21. package/scripts/lib/activation/connect-account.js +145 -0
  22. package/scripts/lib/activation/detect-environment.js +75 -0
  23. package/scripts/lib/activation/detect-hosts.js +62 -0
  24. package/scripts/lib/activation/format-activation-output.js +109 -0
  25. package/scripts/lib/activation/next-action.js +43 -0
  26. package/scripts/lib/activation/repair-engine.js +219 -0
  27. package/scripts/lib/activation-distribution-readiness.js +507 -0
  28. package/scripts/lib/adapter-conformance.js +176 -0
  29. package/scripts/lib/adapter-readiness.js +417 -0
  30. package/scripts/lib/adapter-safety-boundaries.js +335 -0
  31. package/scripts/lib/adapter-technical-readiness-gate.js +205 -0
  32. package/scripts/lib/agent-access-governance.js +455 -0
  33. package/scripts/lib/agent-enforcement.js +765 -0
  34. package/scripts/lib/agent-policy-profile.js +210 -0
  35. package/scripts/lib/agent-security/action-evaluator.js +507 -0
  36. package/scripts/lib/agent-security/adapter-registry.js +98 -0
  37. package/scripts/lib/agent-security/auto-policy.js +139 -0
  38. package/scripts/lib/agent-security/bounded-scan.js +93 -0
  39. package/scripts/lib/agent-security/enforcement-adapter.js +174 -0
  40. package/scripts/lib/agent-security/enforcement-engine.js +1129 -0
  41. package/scripts/lib/agent-security/file-write-adapter.js +183 -0
  42. package/scripts/lib/agent-security/file-write-rules.js +178 -0
  43. package/scripts/lib/agent-security/index.js +3342 -0
  44. package/scripts/lib/agent-security/instruction-risk.js +181 -0
  45. package/scripts/lib/agent-security/mcp-action-adapter.js +185 -0
  46. package/scripts/lib/agent-security/mcp-action-rules.js +184 -0
  47. package/scripts/lib/agent-security/package-action-adapter.js +175 -0
  48. package/scripts/lib/agent-security/package-action-rules.js +233 -0
  49. package/scripts/lib/agent-security/performance.js +148 -0
  50. package/scripts/lib/agent-security/permission-minimizer.js +403 -0
  51. package/scripts/lib/agent-security/scan-cache.js +74 -0
  52. package/scripts/lib/agent-security/source-trust.js +146 -0
  53. package/scripts/lib/ai-install-prompt.js +288 -0
  54. package/scripts/lib/ai-workspace-hygiene.js +1499 -0
  55. package/scripts/lib/alpha-activation.js +520 -0
  56. package/scripts/lib/alpha-feedback.js +263 -0
  57. package/scripts/lib/alpha-readiness-gate.js +332 -0
  58. package/scripts/lib/anti-gaming.js +169 -0
  59. package/scripts/lib/artifact-health.js +431 -0
  60. package/scripts/lib/attribution.js +180 -0
  61. package/scripts/lib/audit.js +289 -0
  62. package/scripts/lib/avorelo-skill-registry.js +810 -0
  63. package/scripts/lib/batch-jobs.js +71 -0
  64. package/scripts/lib/brain-pack.js +578 -0
  65. package/scripts/lib/brand-boundary.js +424 -0
  66. package/scripts/lib/brand.js +74 -0
  67. package/scripts/lib/browser-capability.js +1048 -0
  68. package/scripts/lib/browser-proof-preflight.js +321 -0
  69. package/scripts/lib/cache-readiness.js +187 -0
  70. package/scripts/lib/canonical-reentry.js +162 -0
  71. package/scripts/lib/capability-packs.js +314 -0
  72. package/scripts/lib/capability-recommender.js +512 -0
  73. package/scripts/lib/capability-registry.js +1059 -0
  74. package/scripts/lib/carry-forward-surfacing.js +194 -0
  75. package/scripts/lib/ccusage-adapter.js +188 -0
  76. package/scripts/lib/company-loop.js +1149 -0
  77. package/scripts/lib/config.js +637 -0
  78. package/scripts/lib/context-acquisition-plan.js +287 -0
  79. package/scripts/lib/context-budget-guard.js +170 -0
  80. package/scripts/lib/context-budget-scanner.js +257 -0
  81. package/scripts/lib/context-optimizer.js +715 -0
  82. package/scripts/lib/context-reduction-plan.js +178 -0
  83. package/scripts/lib/context-safety.js +88 -0
  84. package/scripts/lib/context-savings-engine.js +158 -0
  85. package/scripts/lib/cost-evidence.js +254 -0
  86. package/scripts/lib/cross-host-install-plan.js +308 -0
  87. package/scripts/lib/cross-host-install-readiness.js +237 -0
  88. package/scripts/lib/cross-host-value-flow.js +268 -0
  89. package/scripts/lib/dashboard.js +900 -0
  90. package/scripts/lib/design-partner-feedback.js +346 -0
  91. package/scripts/lib/entitlements.js +100 -0
  92. package/scripts/lib/execution-packet.js +559 -0
  93. package/scripts/lib/experimentation-events.js +547 -0
  94. package/scripts/lib/external-capability-compliance.js +107 -0
  95. package/scripts/lib/external-user-simulation.js +166 -0
  96. package/scripts/lib/failure-recovery-readiness.js +81 -0
  97. package/scripts/lib/failure-recovery.js +419 -0
  98. package/scripts/lib/feedback-intelligence.js +537 -0
  99. package/scripts/lib/feedback-signals.js +205 -0
  100. package/scripts/lib/file-integrity.js +68 -0
  101. package/scripts/lib/fsx.js +127 -0
  102. package/scripts/lib/full-readiness-gate.js +451 -0
  103. package/scripts/lib/guidance-builder.js +174 -0
  104. package/scripts/lib/hook-apply.js +1019 -0
  105. package/scripts/lib/hook-baseline.js +310 -0
  106. package/scripts/lib/hook-config-preview.js +275 -0
  107. package/scripts/lib/hook-contracts.js +290 -0
  108. package/scripts/lib/hook-safety-boundary-readiness.js +80 -0
  109. package/scripts/lib/host-capability-matrix.js +351 -0
  110. package/scripts/lib/host-support-context.js +254 -0
  111. package/scripts/lib/http-hook-action.js +538 -0
  112. package/scripts/lib/install-ai-readiness.js +84 -0
  113. package/scripts/lib/install-intake-risk.js +1037 -0
  114. package/scripts/lib/install-journey-intelligence.js +329 -0
  115. package/scripts/lib/intervention-guidance.js +57 -0
  116. package/scripts/lib/known-limitations.js +115 -0
  117. package/scripts/lib/l8-path-truth.js +146 -0
  118. package/scripts/lib/launch-hardening-gate.js +436 -0
  119. package/scripts/lib/launch-readiness.js +628 -0
  120. package/scripts/lib/learning-memory.js +686 -0
  121. package/scripts/lib/lifecycle-hooks.js +802 -0
  122. package/scripts/lib/local-package-smoke.js +423 -0
  123. package/scripts/lib/local-pricing.js +299 -0
  124. package/scripts/lib/mcp-enforcement.js +311 -0
  125. package/scripts/lib/mcp-least-privilege-policy.js +303 -0
  126. package/scripts/lib/mcp-tool-inventory.js +388 -0
  127. package/scripts/lib/mcp-tool-risk.js +0 -0
  128. package/scripts/lib/memory.js +335 -0
  129. package/scripts/lib/metrics.js +699 -0
  130. package/scripts/lib/micro-proof.js +133 -0
  131. package/scripts/lib/next-run-context.js +436 -0
  132. package/scripts/lib/operating-value.js +1648 -0
  133. package/scripts/lib/optimization-v3.js +122 -0
  134. package/scripts/lib/orchestration/adapters/_shared.js +49 -0
  135. package/scripts/lib/orchestration/adapters/aider.js +18 -0
  136. package/scripts/lib/orchestration/adapters/claude-code.js +35 -0
  137. package/scripts/lib/orchestration/adapters/codex.js +35 -0
  138. package/scripts/lib/orchestration/adapters/gemini-cli.js +18 -0
  139. package/scripts/lib/orchestration/adapters/git.js +25 -0
  140. package/scripts/lib/orchestration/adapters/index.js +31 -0
  141. package/scripts/lib/orchestration/adapters/lm-studio.js +18 -0
  142. package/scripts/lib/orchestration/adapters/ollama.js +18 -0
  143. package/scripts/lib/orchestration/adapters/opencode.js +18 -0
  144. package/scripts/lib/orchestration/adapters/openrouter.js +18 -0
  145. package/scripts/lib/orchestration/adapters/test-runner.js +25 -0
  146. package/scripts/lib/orchestration/cli.js +438 -0
  147. package/scripts/lib/orchestration/execution-manager.js +279 -0
  148. package/scripts/lib/orchestration/handoff.js +314 -0
  149. package/scripts/lib/orchestration/index.js +456 -0
  150. package/scripts/lib/orchestration/inventory.js +47 -0
  151. package/scripts/lib/orchestration/model-discovery.js +498 -0
  152. package/scripts/lib/orchestration/model-profiler.js +170 -0
  153. package/scripts/lib/orchestration/model-profiles.js +252 -0
  154. package/scripts/lib/orchestration/model-refresh-policy.js +72 -0
  155. package/scripts/lib/orchestration/proof-writer.js +349 -0
  156. package/scripts/lib/orchestration/provider-discovery/aider.js +49 -0
  157. package/scripts/lib/orchestration/provider-discovery/claude-code.js +56 -0
  158. package/scripts/lib/orchestration/provider-discovery/codex.js +49 -0
  159. package/scripts/lib/orchestration/provider-discovery/common.js +186 -0
  160. package/scripts/lib/orchestration/provider-discovery/gemini.js +106 -0
  161. package/scripts/lib/orchestration/provider-discovery/lm-studio.js +118 -0
  162. package/scripts/lib/orchestration/provider-discovery/models-dev.js +12 -0
  163. package/scripts/lib/orchestration/provider-discovery/ollama.js +100 -0
  164. package/scripts/lib/orchestration/provider-discovery/opencode.js +47 -0
  165. package/scripts/lib/orchestration/provider-discovery/openrouter.js +44 -0
  166. package/scripts/lib/orchestration/risk-classifier.js +130 -0
  167. package/scripts/lib/orchestration/routing-policy.js +486 -0
  168. package/scripts/lib/orchestration/settings.js +112 -0
  169. package/scripts/lib/orchestration/state.js +165 -0
  170. package/scripts/lib/orchestration/verification-manager.js +138 -0
  171. package/scripts/lib/output-profiles.js +146 -0
  172. package/scripts/lib/package-content-audit.js +368 -0
  173. package/scripts/lib/package-runtime.js +278 -0
  174. package/scripts/lib/plan-surface.js +53 -0
  175. package/scripts/lib/plans.js +2318 -0
  176. package/scripts/lib/policy-provider.js +27 -0
  177. package/scripts/lib/prelaunch-activation-readiness.js +409 -0
  178. package/scripts/lib/prelaunch-evidence-store.js +816 -0
  179. package/scripts/lib/prelaunch-intelligence.js +869 -0
  180. package/scripts/lib/pricing-experiment.js +118 -0
  181. package/scripts/lib/pro-moment-events.js +77 -0
  182. package/scripts/lib/pro-moment-state.js +227 -0
  183. package/scripts/lib/pro-moments.js +1216 -0
  184. package/scripts/lib/product-learning-events.js +629 -0
  185. package/scripts/lib/project-profile.js +555 -0
  186. package/scripts/lib/prompt-compiler.js +280 -0
  187. package/scripts/lib/prompt-lint.js +32 -0
  188. package/scripts/lib/prompt-suggestions.js +52 -0
  189. package/scripts/lib/proof-canonical.js +398 -0
  190. package/scripts/lib/proof-drilldown.js +383 -0
  191. package/scripts/lib/proof-events.js +342 -0
  192. package/scripts/lib/proof-history.js +243 -0
  193. package/scripts/lib/proof-metrics.js +296 -0
  194. package/scripts/lib/proof-outcome-evidence.js +134 -0
  195. package/scripts/lib/proof-receipt.js +335 -0
  196. package/scripts/lib/proof-record.js +461 -0
  197. package/scripts/lib/public-activation-distribution-gate.js +258 -0
  198. package/scripts/lib/public-cli.js +3891 -0
  199. package/scripts/lib/public-distribution-truth.js +211 -0
  200. package/scripts/lib/public-install-claim-checker.js +294 -0
  201. package/scripts/lib/publish-provenance-readiness.js +283 -0
  202. package/scripts/lib/readiness-delta.js +218 -0
  203. package/scripts/lib/readiness-evidence-closure.js +196 -0
  204. package/scripts/lib/reentry-memory-capture.js +241 -0
  205. package/scripts/lib/reentry-memory-retrieval.js +302 -0
  206. package/scripts/lib/reentry-memory-status.js +146 -0
  207. package/scripts/lib/reentry-memory-store.js +178 -0
  208. package/scripts/lib/reentry-state.js +66 -0
  209. package/scripts/lib/release-candidate-bundle.js +166 -0
  210. package/scripts/lib/remediation.js +81 -0
  211. package/scripts/lib/repo-map.js +391 -0
  212. package/scripts/lib/run-improvements-lifecycle.js +330 -0
  213. package/scripts/lib/run-improvements.js +789 -0
  214. package/scripts/lib/runtime-decision-policy.js +387 -0
  215. package/scripts/lib/safe-path-engine.js +705 -0
  216. package/scripts/lib/safe-run-controller.js +887 -0
  217. package/scripts/lib/score.js +262 -0
  218. package/scripts/lib/seamless-enforcement.js +329 -0
  219. package/scripts/lib/seamless-outcome.js +689 -0
  220. package/scripts/lib/seamless-reality-gate.js +5043 -0
  221. package/scripts/lib/security-risk-classifier.js +511 -0
  222. package/scripts/lib/security-scan.js +384 -0
  223. package/scripts/lib/session-context-optimizer.js +1211 -0
  224. package/scripts/lib/session-timing.js +315 -0
  225. package/scripts/lib/skill-hygiene.js +805 -0
  226. package/scripts/lib/skill-packs.js +161 -0
  227. package/scripts/lib/skills-operating-layer.js +580 -0
  228. package/scripts/lib/smart-work-routing.js +768 -0
  229. package/scripts/lib/source-catalog.js +700 -0
  230. package/scripts/lib/status-value-summary.js +32 -0
  231. package/scripts/lib/support-bundle.js +578 -0
  232. package/scripts/lib/task-continuation.js +440 -0
  233. package/scripts/lib/test-helpers.js +15 -0
  234. package/scripts/lib/tier.js +38 -0
  235. package/scripts/lib/token-context-quality-gate.js +370 -0
  236. package/scripts/lib/token-cost-capture.js +187 -0
  237. package/scripts/lib/token-cost-intelligence.js +358 -0
  238. package/scripts/lib/token-efficiency-evidence.js +213 -0
  239. package/scripts/lib/token-evidence.js +699 -0
  240. package/scripts/lib/tokenish.js +17 -0
  241. package/scripts/lib/tool-output-sandbox.js +304 -0
  242. package/scripts/lib/trust-audit.js +136 -0
  243. package/scripts/lib/unified-events.js +396 -0
  244. package/scripts/lib/upgrade-interruption-recovery.js +407 -0
  245. package/scripts/lib/usage-ledger.js +201 -0
  246. package/scripts/lib/value-ledger.js +130 -0
  247. package/scripts/lib/value-proof-calibration.js +531 -0
  248. package/scripts/lib/visual-qa.js +231 -0
  249. package/scripts/lib/voice-alpha.js +29 -0
  250. package/scripts/lib/work-aware-orchestration.js +976 -0
  251. package/scripts/lib/work-control-receipts.js +577 -0
  252. package/scripts/lib/work-ledger.js +1123 -0
  253. package/scripts/lib/work-panel-preview.js +352 -0
  254. package/scripts/lib/workflow-discipline.js +280 -0
  255. package/scripts/lib/workflow-signals.js +419 -0
  256. package/scripts/lib/workspace-map.js +281 -0
  257. package/scripts/lib/workspace-registry.js +1367 -0
  258. package/scripts/lib/workspace-resolver.js +480 -0
@@ -0,0 +1,869 @@
1
+ "use strict";
2
+
3
+ // ── Pre-Launch Intelligence Layer ─────────────────────────────────────────────
4
+ //
5
+ // Contract: avorelo.prelaunchIntelligence.v1
6
+ //
7
+ // Aggregates signals from install, activation, feedback, token/cost, MCP,
8
+ // hardening, support and turns them into actionable pre-launch insight.
9
+ //
10
+ // Local-only. Redacted. No public launch claim. No exact savings without source.
11
+ // Not a release candidate gate — this prepares us for that gate.
12
+
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+ const { nowIso } = require("./fsx");
16
+ const { appendProductLearningEvent } = require("./product-learning-events");
17
+
18
+ const CONTRACT = "avorelo.prelaunchIntelligence.v1";
19
+ const SCHEMA_VERSION = 1;
20
+ const INTELLIGENCE_DIR_REL = ".claude/cco/orchestration/prelaunch-intelligence";
21
+ const ARTIFACT_REL = `${INTELLIGENCE_DIR_REL}/latest-intelligence.json`;
22
+
23
+ function safeReadJson(absPath) {
24
+ try {
25
+ if (!fs.existsSync(absPath)) return null;
26
+ return JSON.parse(fs.readFileSync(absPath, "utf8").replace(/^/, ""));
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+
32
+ // ── Signal collection ─────────────────────────────────────────────────────────
33
+
34
+ function collectPrelaunchSignals(cwd, options = {}) {
35
+ const readArtifact = (rel) => safeReadJson(path.join(cwd, rel));
36
+
37
+ // Install / activation signals
38
+ const installPrompt = readArtifact(".claude/cco/orchestration/ai-install/latest-prompt.json");
39
+ const prelaunchReadiness = readArtifact(".claude/cco/orchestration/prelaunch-readiness/latest-activation-readiness.json");
40
+ const activation = readArtifact(".claude/cco/orchestration/activation/latest-activation.json");
41
+ const alphaReadiness = readArtifact(".claude/cco/orchestration/alpha-readiness/latest-gate.json");
42
+
43
+ // Token/cost signals
44
+ const tokenEfficiency = readArtifact(".claude/cco/orchestration/token-efficiency/latest-evidence.json");
45
+ const tokenQualityGate = readArtifact(".claude/cco/orchestration/token-efficiency/latest-quality-gate.json");
46
+ const cacheReadiness = readArtifact(".claude/cco/orchestration/cache-readiness/latest-readiness.json");
47
+
48
+ // MCP signals
49
+ const mcpInventory = readArtifact(".claude/cco/orchestration/mcp-tool-governance/latest-inventory.json");
50
+ const mcpRisk = readArtifact(".claude/cco/orchestration/mcp-tool-governance/latest-risk.json");
51
+ const mcpPolicy = readArtifact(".claude/cco/orchestration/mcp-tool-governance/latest-policy.json");
52
+
53
+ // Hardening signals
54
+ const launchHardening = readArtifact(".claude/cco/orchestration/launch-hardening/latest-gate.json");
55
+ const failureRecovery = readArtifact(".claude/cco/orchestration/failure-recovery/latest-recovery.json");
56
+ const artifactHealth = readArtifact(".claude/cco/orchestration/artifact-health/latest-health.json");
57
+ const hookDoctor = readArtifact(".claude/cco/orchestration/hook-apply/latest-doctor.json");
58
+
59
+ // Support / proof signals
60
+ const supportBundle = readArtifact(".claude/cco/support/latest-support-bundle.json");
61
+ const valueSummary = readArtifact(".claude/cco/orchestration/seamless-outcome/latest-value-summary.json");
62
+ const realityGate = readArtifact(".claude/cco/orchestration/seamless-outcome/latest-reality-gate.json");
63
+ const proofOutcomeEvidence = readArtifact(".claude/cco/orchestration/seamless-outcome/latest-proof-outcome-evidence.json");
64
+ const companyLoop = readArtifact(".claude/cco/orchestration/company-loop/latest-report.json");
65
+ const externalUserSimulation = readArtifact(".claude/cco/orchestration/full-readiness/latest-external-user-simulation.json");
66
+
67
+ // Intelligence sub-surfaces
68
+ const feedbackIntelligence = readArtifact(".claude/cco/orchestration/prelaunch-intelligence/latest-feedback-intelligence.json");
69
+ const tokenCostIntelligence = readArtifact(".claude/cco/orchestration/prelaunch-intelligence/latest-token-cost-intelligence.json");
70
+ const installJourney = readArtifact(".claude/cco/orchestration/prelaunch-intelligence/latest-install-journey.json");
71
+
72
+ return {
73
+ installPrompt,
74
+ prelaunchReadiness,
75
+ activation,
76
+ alphaReadiness,
77
+ tokenEfficiency,
78
+ tokenQualityGate,
79
+ cacheReadiness,
80
+ mcpInventory,
81
+ mcpRisk,
82
+ mcpPolicy,
83
+ launchHardening,
84
+ failureRecovery,
85
+ artifactHealth,
86
+ hookDoctor,
87
+ supportBundle,
88
+ valueSummary,
89
+ realityGate,
90
+ proofOutcomeEvidence,
91
+ companyLoop,
92
+ externalUserSimulation,
93
+ feedbackIntelligence,
94
+ tokenCostIntelligence,
95
+ installJourney,
96
+ };
97
+ }
98
+
99
+ // ── Score computation ─────────────────────────────────────────────────────────
100
+
101
+ function scorePrelaunchSignals(signals, options = {}) {
102
+ let score = 0;
103
+ let maxScore = 0;
104
+ const blockers = [];
105
+ const warnings = [];
106
+ const evidenceMap = {};
107
+
108
+ function addCheck(id, weight, status, description, recoveryAction) {
109
+ maxScore += weight;
110
+ if (status === "pass") {
111
+ score += weight;
112
+ evidenceMap[id] = "pass";
113
+ } else if (status === "warn") {
114
+ score += weight * 0.5;
115
+ evidenceMap[id] = "warn";
116
+ warnings.push({ id, description, recoveryAction });
117
+ } else {
118
+ evidenceMap[id] = "fail";
119
+ blockers.push({ id, description, recoveryAction });
120
+ }
121
+ }
122
+
123
+ // Install prompt (weight 15)
124
+ if (signals.installPrompt?.status === "ready") {
125
+ addCheck("install_prompt", 15, "pass", "AI install prompt ready", null);
126
+ } else if (signals.installPrompt) {
127
+ addCheck("install_prompt", 15, "warn", "AI install prompt present but not ready",
128
+ "Run: node bin/avorelo install-ai --json");
129
+ } else {
130
+ addCheck("install_prompt", 15, "fail", "AI install prompt missing",
131
+ "Run: node bin/avorelo install-ai --json");
132
+ }
133
+
134
+ // Prelaunch readiness (weight 20)
135
+ const plStatus = signals.prelaunchReadiness?.status;
136
+ if (plStatus === "pass") {
137
+ addCheck("prelaunch_readiness", 20, "pass", "Pre-launch readiness passes", null);
138
+ } else if (plStatus === "warn") {
139
+ addCheck("prelaunch_readiness", 20, "warn", "Pre-launch readiness has warnings",
140
+ "Run: node bin/avorelo prelaunch-readiness --json");
141
+ } else {
142
+ addCheck("prelaunch_readiness", 20, "warn", "Pre-launch readiness not yet run",
143
+ "Run: node bin/avorelo prelaunch-readiness --json");
144
+ }
145
+
146
+ // Token/cost evidence (weight 10)
147
+ const tokenLevel = signals.tokenEfficiency?.evidenceLevel;
148
+ if (tokenLevel === "exact" || tokenLevel === "estimated") {
149
+ addCheck("token_cost_evidence", 10, "pass", "Token/cost evidence available", null);
150
+ } else {
151
+ addCheck("token_cost_evidence", 10, "warn", "Token/cost evidence not available",
152
+ "Run: node bin/avorelo token-efficiency --json");
153
+ }
154
+
155
+ // Token quality gate (weight 5)
156
+ const tqStatus = signals.tokenQualityGate?.status;
157
+ if (tqStatus === "pass") {
158
+ addCheck("token_quality_gate", 5, "pass", "Token quality gate passes", null);
159
+ } else if (tqStatus === "warn") {
160
+ addCheck("token_quality_gate", 5, "warn", "Token quality gate warns",
161
+ "Review: node bin/avorelo token-efficiency --json");
162
+ } else {
163
+ addCheck("token_quality_gate", 5, "warn", "Token quality gate not run",
164
+ "Run: node bin/avorelo token-efficiency --json");
165
+ }
166
+
167
+ // MCP governance (weight 10)
168
+ const mcpStatus = signals.mcpInventory?.status;
169
+ if (mcpStatus === "pass" || mcpStatus === "ready") {
170
+ addCheck("mcp_governance", 10, "pass", "MCP governance ready", null);
171
+ } else if (mcpStatus === "warn") {
172
+ addCheck("mcp_governance", 10, "warn", "MCP governance has warnings",
173
+ "Run: node bin/avorelo mcp doctor --json");
174
+ } else {
175
+ addCheck("mcp_governance", 10, "warn", "MCP governance not run",
176
+ "Run: node bin/avorelo mcp doctor --json");
177
+ }
178
+
179
+ // Launch hardening (weight 15)
180
+ const lhStatus = signals.launchHardening?.status;
181
+ if (lhStatus === "pass") {
182
+ addCheck("launch_hardening", 15, "pass", "Launch hardening passes", null);
183
+ } else if (lhStatus === "warn") {
184
+ addCheck("launch_hardening", 15, "warn", `Launch hardening warns (score: ${signals.launchHardening?.score})`,
185
+ "Run: node bin/avorelo launch-hardening --json");
186
+ } else {
187
+ addCheck("launch_hardening", 15, "warn", "Launch hardening not run",
188
+ "Run: node bin/avorelo launch-hardening --json");
189
+ }
190
+
191
+ // Support bundle (weight 5)
192
+ const sbStatus = signals.supportBundle?.status;
193
+ if (sbStatus === "ready") {
194
+ addCheck("support_bundle", 5, "pass", "Support bundle available", null);
195
+ } else {
196
+ addCheck("support_bundle", 5, "warn", "Support bundle not generated",
197
+ "Run: node bin/avorelo support-bundle --json");
198
+ }
199
+
200
+ // Proof/outcome (weight 10)
201
+ if (signals.valueSummary) {
202
+ addCheck("proof_outcome", 10, "pass", "Value summary/proof available", null);
203
+ } else {
204
+ addCheck("proof_outcome", 10, "warn", "No proof or value summary generated",
205
+ "Run: node bin/avorelo proof after completing a task.");
206
+ }
207
+
208
+ // Reality gate (weight 10)
209
+ const rgStatus = signals.realityGate?.status;
210
+ if (rgStatus === "pass") {
211
+ addCheck("reality_gate", 10, "pass", "Reality gate passes", null);
212
+ } else if (rgStatus === "warn") {
213
+ addCheck("reality_gate", 10, "warn", `Reality gate warns (score: ${signals.realityGate?.score})`,
214
+ "Run: node bin/avorelo outcome --gate --json");
215
+ } else {
216
+ addCheck("reality_gate", 10, "warn", "Reality gate not run",
217
+ "Run: node bin/avorelo outcome --gate --json");
218
+ }
219
+
220
+ const normalizedScore = maxScore > 0 ? Math.round((score / maxScore) * 100) : 0;
221
+
222
+ return {
223
+ score: normalizedScore,
224
+ rawScore: score,
225
+ maxScore,
226
+ blockers,
227
+ warnings,
228
+ evidenceMap,
229
+ };
230
+ }
231
+
232
+ // ── Install journey summary ───────────────────────────────────────────────────
233
+
234
+ function buildInstallJourneySummary(signals) {
235
+ const journey = signals.installJourney;
236
+ if (!journey) {
237
+ return {
238
+ status: "not_available",
239
+ stepsComplete: null,
240
+ stepsTotal: null,
241
+ manualStepsAvoided: 0,
242
+ nextAction: "Run: node bin/avorelo install-journey --json",
243
+ };
244
+ }
245
+ return {
246
+ status: journey.status,
247
+ stepsComplete: journey.stepsComplete,
248
+ stepsTotal: journey.stepsTotal,
249
+ manualStepsAvoided: journey.manualStepsAvoided?.length || 0,
250
+ nextAction: journey.nextAction,
251
+ };
252
+ }
253
+
254
+ // ── Friction summary ──────────────────────────────────────────────────────────
255
+
256
+ function buildFrictionSummary(signals) {
257
+ const fi = signals.feedbackIntelligence;
258
+ if (!fi || fi.status === "insufficient_data") {
259
+ return {
260
+ status: "insufficient_data",
261
+ totalEntries: 0,
262
+ topFriction: null,
263
+ clustersFound: 0,
264
+ message: "No feedback entries. Add dogfood feedback to build friction insights.",
265
+ };
266
+ }
267
+ return {
268
+ status: fi.status,
269
+ totalEntries: fi.totalFeedbackEntries || 0,
270
+ topFriction: fi.topFriction,
271
+ clustersFound: fi.clustersFound || 0,
272
+ topClusters: (fi.clusters || []).slice(0, 3).map((c) => ({
273
+ frictionType: c.frictionType,
274
+ count: c.count,
275
+ severity: c.severity,
276
+ recommendedAction: c.recommendedAction,
277
+ })),
278
+ };
279
+ }
280
+
281
+ // ── Token/cost summary ────────────────────────────────────────────────────────
282
+
283
+ function buildTokenCostSummary(signals) {
284
+ const tci = signals.tokenCostIntelligence;
285
+ const te = signals.tokenEfficiency;
286
+
287
+ if (!tci && !te) {
288
+ return {
289
+ evidenceLevel: "not_available",
290
+ status: "not_available",
291
+ noExactSavingsClaim: true,
292
+ message: "Run avorelo token-efficiency --json to generate token evidence.",
293
+ };
294
+ }
295
+
296
+ if (tci) {
297
+ return {
298
+ evidenceLevel: tci.evidenceLevel,
299
+ status: tci.status,
300
+ readinessStatus: tci.readinessStatus || (tci.status === "ready" ? "pass" : tci.status === "partial" ? "warn" : "info"),
301
+ realUsageSamplesCount: tci.realUsageSamplesCount || 0,
302
+ confidence: tci.confidence || "missing",
303
+ evidenceMode: tci.evidenceMode || "missing",
304
+ contextAvoidedEstimate: tci.contextAvoidedEstimate,
305
+ cacheReadinessStatus: tci.cacheReadinessSummary?.status,
306
+ noExactSavingsClaim: true,
307
+ noSavingsClaimUnlessMeasured: tci.noSavingsClaimUnlessMeasured === true,
308
+ caveats: tci.caveats?.slice(0, 2) || [],
309
+ missingEvidence: tci.missingEvidence || [],
310
+ };
311
+ }
312
+
313
+ return {
314
+ evidenceLevel: te.evidenceLevel || "not_available",
315
+ status: te.evidenceLevel ? "partial" : "not_available",
316
+ noExactSavingsClaim: true,
317
+ caveats: ["Token estimates are approximate."],
318
+ };
319
+ }
320
+
321
+ // ── Risk summary ──────────────────────────────────────────────────────────────
322
+
323
+ function buildRiskSummary(signals) {
324
+ const risks = [];
325
+
326
+ // Launch hardening
327
+ const lh = signals.launchHardening;
328
+ if (lh && lh.status !== "pass") {
329
+ risks.push({
330
+ area: "launch_hardening",
331
+ severity: lh.status === "fail" ? "high" : "medium",
332
+ description: `Launch hardening ${lh.status} (score: ${lh.score || "?"})`,
333
+ recoveryAction: "Run: node bin/avorelo launch-hardening --json",
334
+ });
335
+ }
336
+
337
+ // MCP governance
338
+ const mcpRisk = signals.mcpRisk;
339
+ if (mcpRisk?.highRiskCount > 0 || mcpRisk?.unknownCount > 0) {
340
+ risks.push({
341
+ area: "mcp_governance",
342
+ severity: "medium",
343
+ description: `MCP: ${mcpRisk.highRiskCount || 0} high-risk, ${mcpRisk.unknownCount || 0} unknown tools`,
344
+ recoveryAction: "Run: node bin/avorelo mcp doctor --json",
345
+ });
346
+ }
347
+
348
+ // Reality gate
349
+ const rg = signals.realityGate;
350
+ if (rg && rg.status !== "pass") {
351
+ risks.push({
352
+ area: "reality_gate",
353
+ severity: rg.status === "fail" ? "high" : "medium",
354
+ description: `Reality gate ${rg.status} (score: ${rg.score || "?"})`,
355
+ recoveryAction: "Run: node bin/avorelo outcome --gate --json",
356
+ });
357
+ }
358
+
359
+ // Failure recovery
360
+ if (!signals.failureRecovery) {
361
+ risks.push({
362
+ area: "failure_recovery",
363
+ severity: "low",
364
+ description: "Failure recovery plan not generated",
365
+ recoveryAction: "Run: node bin/avorelo launch-hardening --json",
366
+ });
367
+ }
368
+
369
+ return {
370
+ riskCount: risks.length,
371
+ highRiskCount: risks.filter((r) => r.severity === "high").length,
372
+ risks,
373
+ };
374
+ }
375
+
376
+ // ── Support summary ───────────────────────────────────────────────────────────
377
+
378
+ function buildSupportSummary(signals) {
379
+ const sb = signals.supportBundle;
380
+ if (!sb) {
381
+ return {
382
+ status: "not_available",
383
+ artifactsAvailable: 0,
384
+ feedbackItems: 0,
385
+ promptReadinessSummary: null,
386
+ redacted: true,
387
+ };
388
+ }
389
+ return {
390
+ status: sb.status,
391
+ artifactsAvailable: sb.summary?.artifactsAvailable || 0,
392
+ artifactsMissing: sb.summary?.artifactsMissing || 0,
393
+ feedbackItems: sb.summary?.feedbackItems || 0,
394
+ productLearningEvents: sb.summary?.productLearningEvents || 0,
395
+ // Include prompt readiness summary safely (no raw promptText)
396
+ promptReadinessSummary: signals.prelaunchReadiness
397
+ ? {
398
+ status: signals.prelaunchReadiness.status,
399
+ score: signals.prelaunchReadiness.score,
400
+ noPublicLaunchClaim: signals.prelaunchReadiness.noPublicLaunchClaim,
401
+ }
402
+ : null,
403
+ redacted: true,
404
+ };
405
+ }
406
+
407
+ // ── Evidence strength ─────────────────────────────────────────────────────────
408
+
409
+ function buildEvidenceStrength(signals, scoreData) {
410
+ const strongEvidence = Object.values(scoreData.evidenceMap).filter((v) => v === "pass").length;
411
+ const totalChecked = Object.keys(scoreData.evidenceMap).length;
412
+ const evidenceCoverage = totalChecked > 0 ? Math.round((strongEvidence / totalChecked) * 100) : 0;
413
+
414
+ const signalCoverageMap = {
415
+ install: signals.installPrompt ? "available" : "missing",
416
+ prelaunch_readiness: signals.prelaunchReadiness ? "available" : "missing",
417
+ token_efficiency: signals.tokenEfficiency ? "available" : "missing",
418
+ mcp_governance: signals.mcpInventory ? "available" : "missing",
419
+ launch_hardening: signals.launchHardening ? "available" : "missing",
420
+ support_bundle: signals.supportBundle ? "available" : "missing",
421
+ proof_outcome: signals.valueSummary ? "available" : "missing",
422
+ reality_gate: signals.realityGate ? "available" : "missing",
423
+ feedback: signals.feedbackIntelligence?.status === "ready" ? "available" : "partial",
424
+ company_loop: signals.companyLoop ? "available" : "missing",
425
+ };
426
+
427
+ const availableCount = Object.values(signalCoverageMap).filter((v) => v === "available").length;
428
+ const partialCount = Object.values(signalCoverageMap).filter((v) => v === "partial").length;
429
+ const totalSignals = Object.keys(signalCoverageMap).length;
430
+
431
+ let strengthLabel;
432
+ if (availableCount >= totalSignals * 0.8) strengthLabel = "strong";
433
+ else if (availableCount + partialCount >= totalSignals * 0.5) strengthLabel = "moderate";
434
+ else strengthLabel = "weak";
435
+
436
+ return {
437
+ label: strengthLabel,
438
+ evidenceCoverage,
439
+ signalCoverageMap,
440
+ availableSignals: availableCount,
441
+ totalSignals,
442
+ };
443
+ }
444
+
445
+ function buildComponentScores(signals, scoreData) {
446
+ const feedbackScore = signals.feedbackIntelligence?.score || 0;
447
+ const activationEvidenceScore = Math.round(
448
+ [
449
+ signals.installJourney?.status === "ready" ? 100 : 60,
450
+ signals.prelaunchReadiness?.status === "pass" ? 100 : signals.prelaunchReadiness ? 70 : 30,
451
+ signals.valueSummary ? 100 : 20,
452
+ ].reduce((sum, value) => sum + value, 0) / 3
453
+ );
454
+ const costEvidenceScore = signals.tokenCostIntelligence?.status === "ready"
455
+ ? 100
456
+ : signals.tokenCostIntelligence?.status === "partial"
457
+ ? 60
458
+ : 25;
459
+ const readinessEvidenceScore = Math.round(
460
+ [
461
+ signals.launchHardening?.status === "pass" ? 100 : signals.launchHardening ? 70 : 30,
462
+ signals.mcpPolicy?.status === "pass" ? 100 : signals.mcpPolicy ? 70 : 30,
463
+ signals.supportBundle?.status === "ready" ? 100 : signals.supportBundle ? 60 : 30,
464
+ signals.realityGate?.status === "pass" ? 100 : signals.realityGate ? 70 : 30,
465
+ ].reduce((sum, value) => sum + value, 0) / 4
466
+ );
467
+ const simulationCoverageScore = signals.externalUserSimulation
468
+ ? Math.round(((signals.externalUserSimulation.passed || 0) / Math.max(1, signals.externalUserSimulation.totalScenarios || 1)) * 100)
469
+ : 0;
470
+
471
+ return {
472
+ feedbackScore,
473
+ activationEvidenceScore,
474
+ costEvidenceScore,
475
+ readinessEvidenceScore,
476
+ simulationCoverageScore,
477
+ };
478
+ }
479
+
480
+ function buildMissingEvidence(signals, scoreData, frictionSummary, tokenCostSummary) {
481
+ const missingEvidence = [];
482
+ if ((signals.feedbackIntelligence?.qualifiedFeedbackItemsCount || 0) === 0) {
483
+ missingEvidence.push("No qualified redacted feedback evidence is available yet.");
484
+ }
485
+ if ((signals.tokenCostIntelligence?.realUsageSamplesCount || 0) === 0) {
486
+ missingEvidence.push("No real token/cost usage samples are available yet.");
487
+ }
488
+ if (!signals.proofOutcomeEvidence || signals.proofOutcomeEvidence.latestProofAvailable !== true) {
489
+ missingEvidence.push("No proof/value summary artifact is available from a real task.");
490
+ }
491
+ if (!signals.failureRecovery) {
492
+ missingEvidence.push("No failure-recovery plan artifact is available.");
493
+ }
494
+ if (!signals.hookDoctor && !signals.launchHardening) {
495
+ missingEvidence.push("No current hook/failure boundary verification artifact is available.");
496
+ }
497
+ if (frictionSummary.status === "insufficient_data") {
498
+ missingEvidence.push("Feedback coverage is insufficient for friction clustering.");
499
+ }
500
+ if (tokenCostSummary.evidenceMode === "missing" || tokenCostSummary.evidenceLevel === "not_available") {
501
+ missingEvidence.push("Token/cost evidence remains heuristic-only or missing.");
502
+ }
503
+ return missingEvidence;
504
+ }
505
+
506
+ function buildSafeNextActions(signals, scoreData, missingEvidence) {
507
+ const next = [];
508
+ const push = (value) => {
509
+ if (value && !next.includes(value)) next.push(value);
510
+ };
511
+ if ((signals.feedbackIntelligence?.qualifiedFeedbackItemsCount || 0) === 0) {
512
+ push("Run: node bin/avorelo feedback intake-pack --json");
513
+ push("Run: node bin/avorelo feedback import --file <redacted-json-or-jsonl> --json");
514
+ push("Run: node bin/avorelo feedback add --source dogfood --summary \"...\"");
515
+ }
516
+ if ((signals.tokenCostIntelligence?.realUsageSamplesCount || 0) === 0) {
517
+ push("Run: node bin/avorelo token-cost capture --json");
518
+ push("Run: node bin/avorelo token-cost import --file <redacted-json-or-jsonl> --json");
519
+ push("Run: node bin/avorelo token-efficiency --json");
520
+ }
521
+ if (!signals.proofOutcomeEvidence || signals.proofOutcomeEvidence.latestProofAvailable !== true) {
522
+ push("Run: node bin/avorelo proof after completing a real task");
523
+ }
524
+ if (!signals.failureRecovery) {
525
+ push("Run: node bin/avorelo launch-hardening --json");
526
+ }
527
+ if (missingEvidence.length === 0) {
528
+ push("Run: node bin/avorelo full-readiness --json");
529
+ }
530
+ return next;
531
+ }
532
+
533
+ // ── Recommended next PR ───────────────────────────────────────────────────────
534
+
535
+ function buildRecommendedNextPr(signals, scoreData, frictionSummary, riskSummary) {
536
+ const blockers = scoreData.blockers;
537
+ const warnings = scoreData.warnings;
538
+ const topFriction = frictionSummary.topFriction;
539
+ const highRisks = riskSummary.highRiskCount;
540
+
541
+ if ((signals.feedbackIntelligence?.qualifiedFeedbackItemsCount || 0) === 0) {
542
+ return {
543
+ recommendation: "Operational: Import real design-partner feedback",
544
+ rationale: "Readiness still lacks qualified real feedback evidence. The intake primitive exists; the next honest move is collecting and importing redacted real feedback.",
545
+ confidence: "high",
546
+ notRecommendedYet: ["GrowthBook / variants — deferred until feedback and measurement evidence are stronger."],
547
+ };
548
+ }
549
+
550
+ if ((signals.tokenCostIntelligence?.realUsageSamplesCount || 0) === 0) {
551
+ return {
552
+ recommendation: "Operational: Capture/import real token-cost evidence",
553
+ rationale: "Token/cost evidence is still heuristic-only. Measured local samples are needed before stronger efficiency claims.",
554
+ confidence: "high",
555
+ notRecommendedYet: ["Website / pricing — deferred until measured token/cost evidence exists."],
556
+ };
557
+ }
558
+
559
+ // If insufficient data, recommend dogfood first
560
+ if (frictionSummary.status === "insufficient_data" && scoreData.score < 50) {
561
+ return {
562
+ recommendation: "Dogfood / Data Collection",
563
+ rationale: "Insufficient signal data. Run full Avorelo sequence and add dogfood feedback.",
564
+ confidence: "low",
565
+ notRecommendedYet: ["Website / pricing — deferred until Full Readiness Gate"],
566
+ };
567
+ }
568
+
569
+ // If core signals are strong enough, recommend Full Readiness Gate
570
+ if (scoreData.score >= 85 && highRisks === 0 && blockers.length === 0) {
571
+ return {
572
+ recommendation: "Full Readiness / Release Candidate Gate",
573
+ rationale: `Pre-launch intelligence score ${scoreData.score}/100. Core signals strong. Low risk.`,
574
+ confidence: "medium",
575
+ notRecommendedYet: ["Website / pricing — deferred until Full Readiness Gate passes"],
576
+ };
577
+ }
578
+
579
+ // Friction-based recommendations
580
+ if (topFriction === "browser_proof_missing") {
581
+ return {
582
+ recommendation: "Browser Proof / Visual QA Bridge",
583
+ rationale: "Visual proof friction is the dominant cluster.",
584
+ confidence: "medium",
585
+ notRecommendedYet: ["Website / pricing — deferred until Full Readiness Gate"],
586
+ };
587
+ }
588
+
589
+ if (topFriction === "plugin_distribution_unclear") {
590
+ return {
591
+ recommendation: "Plugin / Adapter Technical Readiness",
592
+ rationale: "Plugin distribution friction is the dominant cluster.",
593
+ confidence: "medium",
594
+ notRecommendedYet: ["Website / pricing — deferred until Full Readiness Gate"],
595
+ };
596
+ }
597
+
598
+ if (topFriction === "install_confusion" || topFriction === "ai_prompt_unclear" || topFriction === "hook_approval_unclear") {
599
+ return {
600
+ recommendation: "Install / activation repair",
601
+ rationale: `Install confusion (${topFriction}) is the dominant friction cluster.`,
602
+ confidence: "high",
603
+ notRecommendedYet: ["Website / pricing — deferred until repair complete"],
604
+ };
605
+ }
606
+
607
+ if (topFriction === "token_context_unknown" || topFriction === "exact_savings_unavailable") {
608
+ return {
609
+ recommendation: "Token / cost evidence repair",
610
+ rationale: "Token/cost evidence gaps are the dominant friction cluster.",
611
+ confidence: "medium",
612
+ notRecommendedYet: ["Website / pricing — deferred until Full Readiness Gate"],
613
+ };
614
+ }
615
+
616
+ if (topFriction === "mcp_governance_warn") {
617
+ return {
618
+ recommendation: "MCP governance repair",
619
+ rationale: "MCP governance warnings are the dominant friction cluster.",
620
+ confidence: "medium",
621
+ notRecommendedYet: ["Website / pricing — deferred until Full Readiness Gate"],
622
+ };
623
+ }
624
+
625
+ // Risk-based fallback
626
+ if (highRisks > 0) {
627
+ return {
628
+ recommendation: "Full Readiness / Release Candidate Gate (after risk repair)",
629
+ rationale: `${highRisks} high-risk signals detected. Repair before proceeding.`,
630
+ confidence: "low",
631
+ notRecommendedYet: ["Website / pricing — deferred until all risks resolved"],
632
+ };
633
+ }
634
+
635
+ // Default: head toward Full Readiness Gate
636
+ return {
637
+ recommendation: "Full Readiness / Release Candidate Gate",
638
+ rationale: `Pre-launch intelligence score ${scoreData.score}/100. No dominant blocker cluster.`,
639
+ confidence: "low",
640
+ notRecommendedYet: [
641
+ "Website / pricing — deferred until Full Readiness Gate",
642
+ "Browser Proof — only if visual proof friction dominates",
643
+ "Plugin readiness — only if distribution friction dominates",
644
+ ],
645
+ };
646
+ }
647
+
648
+ // ── Main build function ───────────────────────────────────────────────────────
649
+
650
+ function buildPrelaunchIntelligence(cwd, options = {}) {
651
+ // Ensure sub-intelligences are built
652
+ const { buildFeedbackIntelligence, writeFeedbackIntelligence } = require("./feedback-intelligence");
653
+ const { buildTokenCostRollup, writeTokenCostIntelligence } = require("./token-cost-intelligence");
654
+ const { buildInstallJourneyIntelligence, writeInstallJourneyIntelligence } = require("./install-journey-intelligence");
655
+ const { buildProofOutcomeEvidence, writeProofOutcomeEvidence } = require("./proof-outcome-evidence");
656
+
657
+ const fbIntel = buildFeedbackIntelligence(cwd, options);
658
+ writeFeedbackIntelligence(cwd, fbIntel);
659
+
660
+ const tcIntel = buildTokenCostRollup(cwd, options);
661
+ writeTokenCostIntelligence(cwd, tcIntel);
662
+
663
+ const ijIntel = buildInstallJourneyIntelligence(cwd, options);
664
+ writeInstallJourneyIntelligence(cwd, ijIntel);
665
+ const proofIntel = buildProofOutcomeEvidence(cwd, options);
666
+ writeProofOutcomeEvidence(cwd, proofIntel);
667
+
668
+ // Re-collect signals including the freshly written sub-intelligences
669
+ const signals = collectPrelaunchSignals(cwd, options);
670
+ const scoreData = scorePrelaunchSignals(signals, options);
671
+
672
+ const installJourney = buildInstallJourneySummary(signals);
673
+ const frictionSummary = buildFrictionSummary(signals);
674
+ const tokenCostSummary = buildTokenCostSummary(signals);
675
+ const riskSummary = buildRiskSummary(signals);
676
+ const supportSummary = buildSupportSummary(signals);
677
+ const evidenceStrength = buildEvidenceStrength(signals, scoreData);
678
+ const componentScores = buildComponentScores(signals, scoreData);
679
+ const missingEvidence = buildMissingEvidence(signals, scoreData, frictionSummary, tokenCostSummary);
680
+ const safeNextActions = buildSafeNextActions(signals, scoreData, missingEvidence);
681
+ const recommendedNextPr = buildRecommendedNextPr(signals, scoreData, frictionSummary, riskSummary);
682
+
683
+ // Overall status
684
+ let status;
685
+ if (scoreData.score >= 85 && scoreData.blockers.length === 0) {
686
+ status = "ready";
687
+ } else if (scoreData.score >= 60) {
688
+ status = "warn";
689
+ } else if (evidenceStrength.availableSignals < evidenceStrength.totalSignals * 0.3) {
690
+ status = "insufficient_data";
691
+ } else {
692
+ status = "warn";
693
+ }
694
+
695
+ // Signal coverage summary
696
+ const signalCoverage = {
697
+ installSignals: signals.installPrompt !== null,
698
+ activationSignals: signals.prelaunchReadiness !== null,
699
+ tokenSignals: signals.tokenEfficiency !== null,
700
+ mcpSignals: signals.mcpInventory !== null,
701
+ hardeningSignals: signals.launchHardening !== null,
702
+ supportSignals: signals.supportBundle !== null,
703
+ proofSignals: signals.valueSummary !== null,
704
+ feedbackSignals: (fbIntel.totalFeedbackEntries || 0) > 0,
705
+ companyLoopSignals: signals.companyLoop !== null,
706
+ };
707
+
708
+ // Next action
709
+ let nextAction;
710
+ if (scoreData.blockers.length > 0) {
711
+ nextAction = scoreData.blockers[0].recoveryAction;
712
+ } else if (scoreData.warnings.length > 0) {
713
+ nextAction = scoreData.warnings[0].recoveryAction;
714
+ } else {
715
+ nextAction = recommendedNextPr.recommendation;
716
+ }
717
+
718
+ const intelligence = {
719
+ contract: CONTRACT,
720
+ schemaVersion: SCHEMA_VERSION,
721
+ createdAt: nowIso(),
722
+ status,
723
+ score: scoreData.score,
724
+ signalCoverage,
725
+ componentScores,
726
+ installJourney,
727
+ frictionSummary,
728
+ tokenCostSummary,
729
+ riskSummary,
730
+ supportSummary,
731
+ evidenceStrength,
732
+ missingEvidence,
733
+ safeNextActions,
734
+ recommendedNextPr,
735
+ blockers: scoreData.blockers,
736
+ warnings: scoreData.warnings,
737
+ nextAction,
738
+ noPublicLaunchClaim: true,
739
+ noReleaseReadyClaim: true,
740
+ noReleaseReadyClaimUnlessPassed: true,
741
+ redacted: true,
742
+ };
743
+
744
+ return intelligence;
745
+ }
746
+
747
+ function writePrelaunchIntelligence(cwd, intelligence) {
748
+ const dirAbs = path.join(cwd, INTELLIGENCE_DIR_REL);
749
+ fs.mkdirSync(dirAbs, { recursive: true });
750
+ const absPath = path.join(cwd, ARTIFACT_REL);
751
+ fs.writeFileSync(absPath, JSON.stringify(intelligence, null, 2), "utf8");
752
+ return absPath;
753
+ }
754
+
755
+ function buildPrelaunchIntelligenceSurface(cwd, options = {}) {
756
+ const absPath = path.join(cwd, ARTIFACT_REL);
757
+ const existing = safeReadJson(absPath);
758
+ if (existing && !options.refresh) {
759
+ return {
760
+ status: existing.status,
761
+ score: existing.score,
762
+ recommendedNextPr: existing.recommendedNextPr?.recommendation,
763
+ topFriction: existing.frictionSummary?.topFriction,
764
+ tokenEvidenceLevel: existing.tokenCostSummary?.evidenceLevel,
765
+ artifactPath: ARTIFACT_REL,
766
+ };
767
+ }
768
+ const intel = buildPrelaunchIntelligence(cwd, options);
769
+ writePrelaunchIntelligence(cwd, intel);
770
+
771
+ try {
772
+ appendProductLearningEvent(cwd, {
773
+ eventName: "prelaunch_intelligence_run",
774
+ category: "prelaunch_intelligence",
775
+ status: intel.status,
776
+ score: intel.score,
777
+ recommendedNextPr: intel.recommendedNextPr?.recommendation,
778
+ topFriction: intel.frictionSummary?.topFriction,
779
+ });
780
+ } catch {}
781
+
782
+ return {
783
+ status: intel.status,
784
+ score: intel.score,
785
+ recommendedNextPr: intel.recommendedNextPr?.recommendation,
786
+ topFriction: intel.frictionSummary?.topFriction,
787
+ tokenEvidenceLevel: intel.tokenCostSummary?.evidenceLevel,
788
+ artifactPath: ARTIFACT_REL,
789
+ };
790
+ }
791
+
792
+ function formatPrelaunchIntelligenceText(intelligence, options = {}) {
793
+ const debug = options.debug === true;
794
+ const lines = [];
795
+
796
+ lines.push(`Pre-launch intelligence: ${intelligence.status}`);
797
+ lines.push("");
798
+ lines.push("Signals:");
799
+ lines.push(` Install journey: ${intelligence.installJourney?.status || "not_available"}`);
800
+ lines.push(` Feedback coverage: ${intelligence.frictionSummary?.status || "not_available"}`);
801
+ lines.push(` Token/cost evidence: ${intelligence.tokenCostSummary?.evidenceLevel || "not_available"}`);
802
+ lines.push(` Top friction: ${intelligence.frictionSummary?.topFriction || "none"}`);
803
+ lines.push("");
804
+ lines.push(`Next:`);
805
+ lines.push(` ${intelligence.nextAction || intelligence.recommendedNextPr?.recommendation}`);
806
+ lines.push("");
807
+ lines.push("No launch-ready claim.");
808
+
809
+ if (debug) {
810
+ lines.push("");
811
+ lines.push(`Score: ${intelligence.score}/100`);
812
+ lines.push(`Evidence strength: ${intelligence.evidenceStrength?.label}`);
813
+ if (intelligence.componentScores) {
814
+ lines.push(`Feedback: ${intelligence.componentScores.feedbackScore}/100`);
815
+ lines.push(`Activation evidence: ${intelligence.componentScores.activationEvidenceScore}/100`);
816
+ lines.push(`Cost evidence: ${intelligence.componentScores.costEvidenceScore}/100`);
817
+ lines.push(`Readiness evidence: ${intelligence.componentScores.readinessEvidenceScore}/100`);
818
+ lines.push(`Simulation coverage: ${intelligence.componentScores.simulationCoverageScore}/100`);
819
+ }
820
+ if (intelligence.blockers?.length > 0) {
821
+ lines.push("");
822
+ lines.push(`Blockers (${intelligence.blockers.length}):`);
823
+ for (const b of intelligence.blockers) {
824
+ lines.push(` - ${b.id}: ${b.description}`);
825
+ if (b.recoveryAction) lines.push(` Recovery: ${b.recoveryAction}`);
826
+ }
827
+ }
828
+ if (intelligence.warnings?.length > 0) {
829
+ lines.push("");
830
+ lines.push(`Warnings (${intelligence.warnings.length}):`);
831
+ for (const w of intelligence.warnings.slice(0, 5)) {
832
+ lines.push(` - ${w.id}: ${w.description}`);
833
+ }
834
+ }
835
+ if (intelligence.riskSummary?.risks?.length > 0) {
836
+ lines.push("");
837
+ lines.push("Risks:");
838
+ for (const r of intelligence.riskSummary.risks) {
839
+ lines.push(` [${r.severity}] ${r.area}: ${r.description}`);
840
+ }
841
+ }
842
+ if (intelligence.missingEvidence?.length > 0) {
843
+ lines.push("");
844
+ lines.push("Missing evidence:");
845
+ for (const item of intelligence.missingEvidence.slice(0, 5)) {
846
+ lines.push(` - ${item}`);
847
+ }
848
+ }
849
+ lines.push("");
850
+ lines.push(`Recommended next PR: ${intelligence.recommendedNextPr?.recommendation}`);
851
+ lines.push(`Rationale: ${intelligence.recommendedNextPr?.rationale}`);
852
+ lines.push(`Confidence: ${intelligence.recommendedNextPr?.confidence}`);
853
+ }
854
+
855
+ return lines.join("\n");
856
+ }
857
+
858
+ module.exports = {
859
+ CONTRACT,
860
+ SCHEMA_VERSION,
861
+ ARTIFACT_REL,
862
+ INTELLIGENCE_DIR_REL,
863
+ collectPrelaunchSignals,
864
+ scorePrelaunchSignals,
865
+ buildPrelaunchIntelligence,
866
+ writePrelaunchIntelligence,
867
+ buildPrelaunchIntelligenceSurface,
868
+ formatPrelaunchIntelligenceText,
869
+ };