@ornexus/neocortex 4.59.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/LICENSE +56 -0
  2. package/LICENSE-COMMERCIAL.md +70 -0
  3. package/README.md +58 -0
  4. package/dist/sbom.cdx.json +7067 -0
  5. package/docs/install/coderabbit-manual-setup.md +86 -0
  6. package/docs/install/installer-diagnostics.md +107 -0
  7. package/docs/install/linux-global-install.md +97 -0
  8. package/install.js +572 -0
  9. package/install.ps1 +2214 -0
  10. package/install.sh +2013 -0
  11. package/package.json +118 -0
  12. package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
  13. package/packages/client/dist/adapters/adapter-registry.js +1 -0
  14. package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
  15. package/packages/client/dist/adapters/antigravity-adapter.js +2 -0
  16. package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
  17. package/packages/client/dist/adapters/claude-code-adapter.js +3 -0
  18. package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
  19. package/packages/client/dist/adapters/codex-adapter.js +2 -0
  20. package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
  21. package/packages/client/dist/adapters/cursor-adapter.js +4 -0
  22. package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
  23. package/packages/client/dist/adapters/gemini-adapter.js +2 -0
  24. package/packages/client/dist/adapters/index.d.ts +19 -0
  25. package/packages/client/dist/adapters/index.js +1 -0
  26. package/packages/client/dist/adapters/platform-detector.d.ts +48 -0
  27. package/packages/client/dist/adapters/platform-detector.js +1 -0
  28. package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
  29. package/packages/client/dist/adapters/target-adapter.js +0 -0
  30. package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
  31. package/packages/client/dist/adapters/vscode-adapter.js +2 -0
  32. package/packages/client/dist/agent/refresh-stubs.d.ts +80 -0
  33. package/packages/client/dist/agent/refresh-stubs.js +2 -0
  34. package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
  35. package/packages/client/dist/agent/update-agent-yaml.js +1 -0
  36. package/packages/client/dist/agent/update-description.d.ts +45 -0
  37. package/packages/client/dist/agent/update-description.js +1 -0
  38. package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
  39. package/packages/client/dist/cache/crypto-utils.js +1 -0
  40. package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
  41. package/packages/client/dist/cache/encrypted-cache.js +1 -0
  42. package/packages/client/dist/cache/in-memory-asset-cache.d.ts +62 -0
  43. package/packages/client/dist/cache/in-memory-asset-cache.js +1 -0
  44. package/packages/client/dist/cache/index.d.ts +13 -0
  45. package/packages/client/dist/cache/index.js +1 -0
  46. package/packages/client/dist/cache/protected-pi-boundary.d.ts +19 -0
  47. package/packages/client/dist/cache/protected-pi-boundary.js +1 -0
  48. package/packages/client/dist/checkpoint/checkpoint-client-reader.d.ts +45 -0
  49. package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -0
  50. package/packages/client/dist/checkpoint/index.d.ts +12 -0
  51. package/packages/client/dist/checkpoint/index.js +1 -0
  52. package/packages/client/dist/checkpoint/shared-checkpoint-types.d.ts +85 -0
  53. package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -0
  54. package/packages/client/dist/cli.d.ts +14 -0
  55. package/packages/client/dist/cli.js +48 -0
  56. package/packages/client/dist/commands/activate.d.ts +55 -0
  57. package/packages/client/dist/commands/activate.js +8 -0
  58. package/packages/client/dist/commands/cache-status.d.ts +39 -0
  59. package/packages/client/dist/commands/cache-status.js +2 -0
  60. package/packages/client/dist/commands/invoke.d.ts +229 -0
  61. package/packages/client/dist/commands/invoke.js +63 -0
  62. package/packages/client/dist/commands/refresh-memory.d.ts +11 -0
  63. package/packages/client/dist/commands/refresh-memory.js +1 -0
  64. package/packages/client/dist/config/resolver-selection.d.ts +40 -0
  65. package/packages/client/dist/config/resolver-selection.js +1 -0
  66. package/packages/client/dist/config/secure-config.d.ts +78 -0
  67. package/packages/client/dist/config/secure-config.js +12 -0
  68. package/packages/client/dist/constants.d.ts +25 -0
  69. package/packages/client/dist/constants.js +1 -0
  70. package/packages/client/dist/context/context-collector.d.ts +28 -0
  71. package/packages/client/dist/context/context-collector.js +2 -0
  72. package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
  73. package/packages/client/dist/context/context-sanitizer.js +1 -0
  74. package/packages/client/dist/continuity/continuity-client-state-store.d.ts +183 -0
  75. package/packages/client/dist/continuity/continuity-client-state-store.js +1 -0
  76. package/packages/client/dist/continuity/invoke-hooks.d.ts +18 -0
  77. package/packages/client/dist/continuity/invoke-hooks.js +1 -0
  78. package/packages/client/dist/continuity/migrations/001-initial-schema.d.ts +11 -0
  79. package/packages/client/dist/continuity/migrations/001-initial-schema.js +263 -0
  80. package/packages/client/dist/continuity/sqlite-store.d.ts +409 -0
  81. package/packages/client/dist/continuity/sqlite-store.js +226 -0
  82. package/packages/client/dist/errors/error-messages.d.ts +40 -0
  83. package/packages/client/dist/errors/error-messages.js +2 -0
  84. package/packages/client/dist/graph-retrieval/pre-command-hook.d.ts +31 -0
  85. package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -0
  86. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.d.ts +77 -0
  87. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -0
  88. package/packages/client/dist/i18n/first-run.d.ts +23 -0
  89. package/packages/client/dist/i18n/first-run.js +2 -0
  90. package/packages/client/dist/index.d.ts +56 -0
  91. package/packages/client/dist/index.js +1 -0
  92. package/packages/client/dist/license/index.d.ts +5 -0
  93. package/packages/client/dist/license/index.js +1 -0
  94. package/packages/client/dist/license/license-client.d.ts +79 -0
  95. package/packages/client/dist/license/license-client.js +1 -0
  96. package/packages/client/dist/machine/fingerprint.d.ts +34 -0
  97. package/packages/client/dist/machine/fingerprint.js +2 -0
  98. package/packages/client/dist/machine/index.d.ts +5 -0
  99. package/packages/client/dist/machine/index.js +1 -0
  100. package/packages/client/dist/memory/project-memory-writer.d.ts +74 -0
  101. package/packages/client/dist/memory/project-memory-writer.js +36 -0
  102. package/packages/client/dist/memory/shared-project-memory-types.d.ts +370 -0
  103. package/packages/client/dist/memory/shared-project-memory-types.js +2 -0
  104. package/packages/client/dist/policy/architecture-policy.d.ts +40 -0
  105. package/packages/client/dist/policy/architecture-policy.js +2 -0
  106. package/packages/client/dist/policy/index.d.ts +8 -0
  107. package/packages/client/dist/policy/index.js +1 -0
  108. package/packages/client/dist/policy/shared-policy-types.d.ts +89 -0
  109. package/packages/client/dist/policy/shared-policy-types.js +0 -0
  110. package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
  111. package/packages/client/dist/resilience/circuit-breaker.js +1 -0
  112. package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
  113. package/packages/client/dist/resilience/degradation-manager.js +1 -0
  114. package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
  115. package/packages/client/dist/resilience/freshness-indicator.js +1 -0
  116. package/packages/client/dist/resilience/index.d.ts +8 -0
  117. package/packages/client/dist/resilience/index.js +1 -0
  118. package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
  119. package/packages/client/dist/resilience/recovery-detector.js +1 -0
  120. package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
  121. package/packages/client/dist/resolvers/asset-resolver.js +0 -0
  122. package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
  123. package/packages/client/dist/resolvers/local-resolver.js +8 -0
  124. package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
  125. package/packages/client/dist/resolvers/remote-resolver.js +1 -0
  126. package/packages/client/dist/runner/cli.d.ts +121 -0
  127. package/packages/client/dist/runner/cli.js +20 -0
  128. package/packages/client/dist/runner/scheduler.d.ts +116 -0
  129. package/packages/client/dist/runner/scheduler.js +6 -0
  130. package/packages/client/dist/runner-cli.d.ts +9 -0
  131. package/packages/client/dist/runner-cli.js +3 -0
  132. package/packages/client/dist/state/project-state-snapshot.d.ts +15 -0
  133. package/packages/client/dist/state/project-state-snapshot.js +1 -0
  134. package/packages/client/dist/state/state-json-repair.d.ts +17 -0
  135. package/packages/client/dist/state/state-json-repair.js +3 -0
  136. package/packages/client/dist/telemetry/index.d.ts +5 -0
  137. package/packages/client/dist/telemetry/index.js +1 -0
  138. package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
  139. package/packages/client/dist/telemetry/offline-queue.js +1 -0
  140. package/packages/client/dist/tier/index.d.ts +5 -0
  141. package/packages/client/dist/tier/index.js +1 -0
  142. package/packages/client/dist/tier/tier-aware-client.d.ts +105 -0
  143. package/packages/client/dist/tier/tier-aware-client.js +1 -0
  144. package/packages/client/dist/types/index.d.ts +140 -0
  145. package/packages/client/dist/types/index.js +1 -0
  146. package/packages/client/dist/yoloop/discovery-hook.d.ts +85 -0
  147. package/packages/client/dist/yoloop/discovery-hook.js +2 -0
  148. package/packages/client/dist/yoloop/index.d.ts +10 -0
  149. package/packages/client/dist/yoloop/index.js +1 -0
  150. package/packages/client/dist/yoloop/invoke-hooks.d.ts +125 -0
  151. package/packages/client/dist/yoloop/invoke-hooks.js +5 -0
  152. package/packages/client/dist/yoloop/shared-discover-epics.d.ts +289 -0
  153. package/packages/client/dist/yoloop/shared-discover-epics.js +1 -0
  154. package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +172 -0
  155. package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -0
  156. package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +124 -0
  157. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -0
  158. package/postinstall.js +754 -0
  159. package/targets-stubs/antigravity/README.md +36 -0
  160. package/targets-stubs/antigravity/gemini.md +29 -0
  161. package/targets-stubs/antigravity/install-antigravity.sh +153 -0
  162. package/targets-stubs/antigravity/mcp-config.json +30 -0
  163. package/targets-stubs/antigravity/skill/SKILL.md +159 -0
  164. package/targets-stubs/claude-code/.mcp.json +32 -0
  165. package/targets-stubs/claude-code/README.md +20 -0
  166. package/targets-stubs/claude-code/neocortex-root.agent.yaml +42 -0
  167. package/targets-stubs/claude-code/neocortex-root.md +310 -0
  168. package/targets-stubs/claude-code/neocortex.agent.yaml +42 -0
  169. package/targets-stubs/claude-code/neocortex.md +378 -0
  170. package/targets-stubs/codex/AGENTS.md +244 -0
  171. package/targets-stubs/codex/README.md +47 -0
  172. package/targets-stubs/codex/config-mcp.toml +22 -0
  173. package/targets-stubs/codex/install-codex.sh +63 -0
  174. package/targets-stubs/codex/neocortex.toml +29 -0
  175. package/targets-stubs/cursor/README.md +33 -0
  176. package/targets-stubs/cursor/agent.md +204 -0
  177. package/targets-stubs/cursor/install-cursor.sh +50 -0
  178. package/targets-stubs/cursor/mcp.json +30 -0
  179. package/targets-stubs/gemini-cli/README.md +34 -0
  180. package/targets-stubs/gemini-cli/agent.md +234 -0
  181. package/targets-stubs/gemini-cli/agents/neocortex.md +54 -0
  182. package/targets-stubs/gemini-cli/gemini.md +46 -0
  183. package/targets-stubs/gemini-cli/install-gemini.sh +70 -0
  184. package/targets-stubs/gemini-cli/settings-mcp.json +30 -0
  185. package/targets-stubs/kimi/mcp.json +33 -0
  186. package/targets-stubs/kimi/neocortex.md +54 -0
  187. package/targets-stubs/lib/mcp-merge.js +189 -0
  188. package/targets-stubs/openclaw/README.md +12 -0
  189. package/targets-stubs/openclaw/SKILL.md +88 -0
  190. package/targets-stubs/opencode/neocortex-root.md +261 -0
  191. package/targets-stubs/opencode/neocortex.md +59 -0
  192. package/targets-stubs/opencode/opencode-mcp.json +35 -0
  193. package/targets-stubs/vscode/README.md +34 -0
  194. package/targets-stubs/vscode/copilot-instructions.md +47 -0
  195. package/targets-stubs/vscode/install-vscode.sh +72 -0
  196. package/targets-stubs/vscode/mcp.json +36 -0
  197. package/targets-stubs/vscode/neocortex.agent.md +245 -0
package/postinstall.js ADDED
@@ -0,0 +1,754 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Neocortex - Postinstall Hook
5
+ *
6
+ * For global installs: auto-runs the installer in quiet/auto mode.
7
+ * For local installs: prints usage message.
8
+ *
9
+ * NEVER fails npm install -- always exits 0.
10
+ *
11
+ * Epic 62 - GAP 6
12
+ */
13
+
14
+ const { spawn } = require('child_process');
15
+ const path = require('path');
16
+ const os = require('os');
17
+ const fs = require('fs');
18
+
19
+ const DEFAULT_INITIAL_CHILD_TIMEOUT_MS = 3 * 60 * 1000;
20
+ const DEFAULT_RETRY_CHILD_TIMEOUT_MS = 60 * 1000;
21
+ const DEFAULT_CLEANUP_TIMEOUT_MS = 2 * 1000;
22
+ const DEFAULT_KILL_SIGNAL = 'SIGTERM';
23
+
24
+ const liveChildren = new Set();
25
+ const PUBLIC_DIAGNOSTIC_PREFIX = '[neocortex-installer]';
26
+ const DEFAULT_OPTIONAL_TOOL_DOC = 'docs/install/coderabbit-manual-setup.md';
27
+ const RAW_DIAGNOSTIC_FIELDS = [
28
+ 'stdout',
29
+ 'stderr',
30
+ 'output',
31
+ 'rawOutput',
32
+ 'rawLog',
33
+ 'logs',
34
+ 'message',
35
+ 'stack',
36
+ ];
37
+
38
+ function clampPublicText(value, maxLength = 160) {
39
+ const text = String(value ?? '')
40
+ .replace(/[\r\n\t]+/g, ' ')
41
+ .replace(/[\x00-\x1F\x7F]/g, '')
42
+ .replace(/\/home\/[^\s"']+/g, '<redacted-path>')
43
+ .replace(/\/Users\/[^\s"']+/g, '<redacted-path>')
44
+ .replace(/C:\\Users\\[^\s"']+/gi, '<redacted-path>')
45
+ .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, '<redacted-email>')
46
+ .replace(/\b(?:NX|ghp|github_pat|ctx7sk|sk|pk)[_-][A-Za-z0-9_.-]{8,}\b/g, '<redacted-token>')
47
+ .trim();
48
+ return text.length > maxLength ? `${text.slice(0, Math.max(0, maxLength - 3))}...` : text;
49
+ }
50
+
51
+ function sanitizeDiagnosticToken(value, fallback = 'unknown', maxLength = 80) {
52
+ const cleaned = clampPublicText(value ?? fallback, maxLength)
53
+ .replace(/[^A-Za-z0-9_.:/-]/g, '_')
54
+ .replace(/_+/g, '_')
55
+ .replace(/^_+|_+$/g, '');
56
+ return cleaned || fallback;
57
+ }
58
+
59
+ function sanitizeReasonCode(value) {
60
+ return sanitizeDiagnosticToken(value || 'P177_MANDATORY_INSTALL_FAILED', 'P177_MANDATORY_INSTALL_FAILED', 96)
61
+ .toUpperCase();
62
+ }
63
+
64
+ function normalizePublicCode(value) {
65
+ if (value === null || value === undefined) return 'null';
66
+ if (typeof value === 'number' && Number.isFinite(value)) return String(value);
67
+ return sanitizeDiagnosticToken(value, 'unknown', 48);
68
+ }
69
+
70
+ function normalizePublicSignal(value) {
71
+ if (value === null || value === undefined || value === '') return 'null';
72
+ return sanitizeDiagnosticToken(value, 'unknown', 48).toUpperCase();
73
+ }
74
+
75
+ function normalizeRetryAttempt(value) {
76
+ const parsed = Number.parseInt(String(value ?? 0), 10);
77
+ if (!Number.isFinite(parsed) || parsed < 0) return 0;
78
+ return Math.min(parsed, 99);
79
+ }
80
+
81
+ function normalizeTimeoutMs(value) {
82
+ const parsed = Number.parseInt(String(value ?? ''), 10);
83
+ if (!Number.isFinite(parsed) || parsed < 0) return null;
84
+ return Math.min(parsed, 24 * 60 * 60 * 1000);
85
+ }
86
+
87
+ function hasRawDiagnosticFields(result = {}) {
88
+ return RAW_DIAGNOSTIC_FIELDS.some((field) => result[field] !== undefined && result[field] !== null && result[field] !== '');
89
+ }
90
+
91
+ function deriveDiagnosticStatus(result = {}, reasonCode = '') {
92
+ if (reasonCode === 'P177_CHILD_SUCCESS') return 'success';
93
+ if (reasonCode.includes('SKIPPED') || reasonCode.includes('OPT_IN_REQUIRED')) return 'skipped';
94
+ if (reasonCode.includes('ROOT_HOME') || reasonCode.includes('PARENT_INTERRUPTED')) return 'warning';
95
+ if (result.timedOut || reasonCode.includes('TIMEOUT')) return 'failed';
96
+ if (result.signal || reasonCode.includes('SIGNAL')) return 'failed';
97
+ if (result.errorReason || reasonCode.includes('SPAWN_ERROR')) return 'failed';
98
+ if (result.code !== 0 && result.code !== null && result.code !== undefined) return 'failed';
99
+ return 'info';
100
+ }
101
+
102
+ function buildPublicInstallerDiagnostic(result = {}, options = {}) {
103
+ const raw = result && typeof result === 'object' ? result : {};
104
+ const optional = options.optional === true || raw.optional === true;
105
+ const reasonCode = sanitizeReasonCode(
106
+ options.reasonCode || raw.reasonCode || classifyChildResult(raw, { optional }),
107
+ );
108
+ const tool = sanitizeDiagnosticToken(
109
+ options.tool || raw.tool || (optional ? 'optional-tool' : 'neocortex'),
110
+ 'neocortex',
111
+ 64,
112
+ );
113
+ const phase = sanitizeDiagnosticToken(
114
+ options.phase || raw.phase || (optional ? 'optional-tool-setup' : 'postinstall-child'),
115
+ 'postinstall-child',
116
+ 96,
117
+ );
118
+ const timeoutMs = normalizeTimeoutMs(options.timeoutMs ?? raw.timeoutMs);
119
+ const redacted = options.redacted === true || hasRawDiagnosticFields(raw);
120
+ const diagnostic = {
121
+ tool,
122
+ phase,
123
+ status: sanitizeDiagnosticToken(
124
+ options.status || raw.status || deriveDiagnosticStatus(raw, reasonCode),
125
+ 'info',
126
+ 32,
127
+ ),
128
+ reasonCode,
129
+ code: normalizePublicCode(options.code ?? raw.code),
130
+ signal: normalizePublicSignal(options.signal ?? raw.signal),
131
+ timedOut: (options.timedOut ?? raw.timedOut) === true,
132
+ retryAttempt: normalizeRetryAttempt(options.retryAttempt ?? raw.retryAttempt),
133
+ optional,
134
+ summary: clampPublicText(
135
+ options.summary || raw.summary || publicDiagnosticSummary(reasonCode),
136
+ 220,
137
+ ),
138
+ };
139
+
140
+ if (timeoutMs !== null) diagnostic.timeoutMs = timeoutMs;
141
+ if (raw.cleanupTimedOut === true || options.cleanupTimedOut === true) diagnostic.cleanupTimedOut = true;
142
+ if (raw.errorCode || options.errorCode) {
143
+ diagnostic.errorCode = sanitizeDiagnosticToken(options.errorCode || raw.errorCode, 'spawn-error', 80);
144
+ }
145
+ if (options.docPath || raw.docPath) {
146
+ diagnostic.docPath = sanitizeDiagnosticToken(options.docPath || raw.docPath, DEFAULT_OPTIONAL_TOOL_DOC, 120);
147
+ }
148
+ if (redacted) {
149
+ diagnostic.redacted = true;
150
+ diagnostic.redactionReasonCode = 'P177_PUBLIC_SAFE_LOG_REDACTED';
151
+ }
152
+
153
+ return diagnostic;
154
+ }
155
+
156
+ function publicDiagnosticSummary(reasonCode) {
157
+ switch (reasonCode) {
158
+ case 'P177_OPTIONAL_TOOL_SKIPPED_CI':
159
+ return 'Optional third-party setup skipped in CI; no external installer invoked.';
160
+ case 'P177_OPTIONAL_TOOL_SKIPPED_NONINTERACTIVE':
161
+ return 'Optional third-party setup skipped in non-interactive install; no external installer invoked.';
162
+ case 'P177_OPTIONAL_TOOL_OPT_IN_REQUIRED':
163
+ return 'Optional third-party setup requires explicit manual opt-in.';
164
+ case 'P177_OPTIONAL_TOOL_SIGNAL':
165
+ case 'P177_CHILD_SIGNAL':
166
+ return 'Child process ended due to a signal; diagnostic is sanitized and bounded.';
167
+ case 'P177_OPTIONAL_TOOL_TIMEOUT':
168
+ case 'P177_CHILD_TIMEOUT':
169
+ return 'Child process exceeded a bounded timeout; raw child output is omitted.';
170
+ case 'P177_OPTIONAL_TOOL_SPAWN_ERROR':
171
+ case 'P177_CHILD_SPAWN_ERROR':
172
+ return 'Child process could not be spawned; diagnostic includes only public error metadata.';
173
+ case 'P177_PARENT_INTERRUPTED':
174
+ return 'Parent lifecycle received an interruption and attempted child cleanup.';
175
+ case 'P177_ROOT_HOME_DETECTED':
176
+ return 'Elevated install context may target an unintended root-owned HOME.';
177
+ case 'P177_CHILD_RETRY_EXHAUSTED':
178
+ return 'Bounded retry budget was exhausted; raw retry output is not persisted.';
179
+ default:
180
+ return 'Installer diagnostic emitted with public-safe bounded metadata.';
181
+ }
182
+ }
183
+
184
+ function formatPublicInstallerDiagnostic(diagnostic) {
185
+ const fields = [
186
+ `tool=${diagnostic.tool}`,
187
+ `phase=${diagnostic.phase}`,
188
+ `status=${diagnostic.status}`,
189
+ `reasonCode=${diagnostic.reasonCode}`,
190
+ `code=${diagnostic.code}`,
191
+ `signal=${diagnostic.signal}`,
192
+ `timedOut=${diagnostic.timedOut === true}`,
193
+ `retryAttempt=${diagnostic.retryAttempt}`,
194
+ ];
195
+ if (diagnostic.timeoutMs !== undefined) fields.push(`timeoutMs=${diagnostic.timeoutMs}`);
196
+ if (diagnostic.cleanupTimedOut) fields.push('cleanupTimedOut=true');
197
+ if (diagnostic.errorCode) fields.push(`errorCode=${diagnostic.errorCode}`);
198
+ if (diagnostic.docPath) fields.push(`docPath=${diagnostic.docPath}`);
199
+ if (diagnostic.redacted) fields.push(`redactionReasonCode=${diagnostic.redactionReasonCode}`);
200
+ fields.push(`summary=${JSON.stringify(diagnostic.summary)}`);
201
+ return `${PUBLIC_DIAGNOSTIC_PREFIX} ${fields.join(' ')}`;
202
+ }
203
+
204
+ function getSanitizedTroubleshootingText(reasonCode) {
205
+ const code = sanitizeReasonCode(reasonCode);
206
+ if (code.includes('SIGNAL') || code === 'P177_PARENT_INTERRUPTED') {
207
+ return [
208
+ 'Troubleshooting: npm lifecycle observed a sanitized interruption after installer output.',
209
+ 'Retry in a fresh non-sudo shell; optional third-party setup remains manual and raw child output is intentionally omitted.',
210
+ ];
211
+ }
212
+ if (code.includes('TIMEOUT')) {
213
+ return [
214
+ 'Troubleshooting: a bounded installer child timed out; retry after checking network and shell availability.',
215
+ 'Diagnostics include timeout metadata only and exclude raw child output.',
216
+ ];
217
+ }
218
+ if (code.includes('SPAWN_ERROR')) {
219
+ return [
220
+ 'Troubleshooting: an installer child could not start; verify required shell tooling is available.',
221
+ 'Diagnostics include sanitized spawn metadata only and exclude local paths or raw error output.',
222
+ ];
223
+ }
224
+ return [];
225
+ }
226
+
227
+ function parsePositiveInteger(value, fallback) {
228
+ const parsed = Number.parseInt(String(value || ''), 10);
229
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
230
+ }
231
+
232
+ function getPostinstallTimeouts(env = process.env) {
233
+ return {
234
+ initialMs: parsePositiveInteger(
235
+ env.NEOCORTEX_POSTINSTALL_TIMEOUT_MS,
236
+ DEFAULT_INITIAL_CHILD_TIMEOUT_MS,
237
+ ),
238
+ retryMs: parsePositiveInteger(
239
+ env.NEOCORTEX_POSTINSTALL_RETRY_TIMEOUT_MS,
240
+ DEFAULT_RETRY_CHILD_TIMEOUT_MS,
241
+ ),
242
+ cleanupMs: parsePositiveInteger(
243
+ env.NEOCORTEX_POSTINSTALL_CLEANUP_TIMEOUT_MS,
244
+ DEFAULT_CLEANUP_TIMEOUT_MS,
245
+ ),
246
+ };
247
+ }
248
+
249
+ function isSuccessfulChildResult(result) {
250
+ return Boolean(result)
251
+ && result.code === 0
252
+ && result.signal === null
253
+ && result.timedOut !== true
254
+ && !result.errorReason;
255
+ }
256
+
257
+ function classifyChildResult(result, options = {}) {
258
+ const optional = options.optional === true || result?.optional === true;
259
+ if (!result) return optional ? 'P177_OPTIONAL_TOOL_MISSING_DEPENDENCY' : 'P177_MANDATORY_INSTALL_FAILED';
260
+ if (result.timedOut) return optional ? 'P177_OPTIONAL_TOOL_TIMEOUT' : 'P177_CHILD_TIMEOUT';
261
+ if (result.errorReason) return optional ? 'P177_OPTIONAL_TOOL_SPAWN_ERROR' : 'P177_CHILD_SPAWN_ERROR';
262
+ if (result.signal) return optional ? 'P177_OPTIONAL_TOOL_SIGNAL' : 'P177_CHILD_SIGNAL';
263
+ if (result.code === 0) return 'P177_CHILD_SUCCESS';
264
+ if (result.code !== null && result.code !== undefined) return 'P177_CHILD_NONZERO';
265
+ return optional ? 'P177_OPTIONAL_TOOL_MISSING_DEPENDENCY' : 'P177_MANDATORY_INSTALL_FAILED';
266
+ }
267
+
268
+ function sanitizeErrorCode(error) {
269
+ const code = typeof error?.code === 'string' ? error.code : 'spawn-error';
270
+ return code.replace(/[^A-Z0-9_.-]/gi, '_').slice(0, 80);
271
+ }
272
+
273
+ function emitPublicDiagnostic(result, runtime = {}) {
274
+ if (!result?.reasonCode || result.reasonCode === 'P177_CHILD_SUCCESS') return null;
275
+ const logger = runtime.console || console;
276
+ const diagnostic = buildPublicInstallerDiagnostic(result, {
277
+ tool: result.tool || (result.optional ? 'optional-tool' : 'neocortex'),
278
+ });
279
+ logger.error(formatPublicInstallerDiagnostic(diagnostic));
280
+ return diagnostic;
281
+ }
282
+
283
+ function killChild(child, signal = DEFAULT_KILL_SIGNAL) {
284
+ try {
285
+ if (child && typeof child.kill === 'function' && child.killed !== true) {
286
+ child.kill(signal);
287
+ return true;
288
+ }
289
+ } catch { /* public-safe best effort */ }
290
+ return false;
291
+ }
292
+
293
+ function terminateLiveChildren(signal = DEFAULT_KILL_SIGNAL, runtime = {}) {
294
+ const children = runtime.liveChildren || liveChildren;
295
+ for (const child of Array.from(children)) {
296
+ killChild(child, signal);
297
+ }
298
+ }
299
+
300
+ function installParentSignalHandlers(runtime = {}) {
301
+ const processLike = runtime.process || process;
302
+ const signals = ['SIGINT', 'SIGTERM'];
303
+ const handlers = [];
304
+
305
+ for (const signal of signals) {
306
+ const handler = () => {
307
+ const diagnostic = {
308
+ reasonCode: 'P177_PARENT_INTERRUPTED',
309
+ phase: 'parent-signal-cleanup',
310
+ code: null,
311
+ signal,
312
+ timedOut: false,
313
+ retryAttempt: 0,
314
+ };
315
+ emitPublicDiagnostic(diagnostic, runtime);
316
+ terminateLiveChildren(DEFAULT_KILL_SIGNAL, runtime);
317
+ try { processLike.exitCode = 0; } catch { /* ignore */ }
318
+ const exitFn = typeof processLike.exit === 'function' ? processLike.exit.bind(processLike) : null;
319
+ if (exitFn) {
320
+ const timer = setTimeout(() => exitFn(0), 25);
321
+ if (typeof timer.unref === 'function') timer.unref();
322
+ }
323
+ };
324
+
325
+ if (typeof processLike.once === 'function') {
326
+ processLike.once(signal, handler);
327
+ handlers.push([signal, handler]);
328
+ }
329
+ }
330
+
331
+ return () => {
332
+ for (const [signal, handler] of handlers) {
333
+ try {
334
+ if (typeof processLike.off === 'function') processLike.off(signal, handler);
335
+ else if (typeof processLike.removeListener === 'function') processLike.removeListener(signal, handler);
336
+ } catch { /* ignore */ }
337
+ }
338
+ };
339
+ }
340
+
341
+ function runBoundedChild(command, args = [], options = {}, runtime = {}) {
342
+ const spawnFn = runtime.spawn || spawn;
343
+ const children = runtime.liveChildren || liveChildren;
344
+ const timeoutMs = parsePositiveInteger(options.timeoutMs, DEFAULT_INITIAL_CHILD_TIMEOUT_MS);
345
+ const cleanupTimeoutMs = parsePositiveInteger(options.cleanupTimeoutMs, DEFAULT_CLEANUP_TIMEOUT_MS);
346
+ const killSignal = options.killSignal || DEFAULT_KILL_SIGNAL;
347
+ const phase = options.phase || 'postinstall-child';
348
+ const retryAttempt = options.retryAttempt || 0;
349
+ const optional = options.optional === true;
350
+ const commandLabel = options.commandLabel || path.basename(String(command || 'child'));
351
+ const spawnOptions = { ...(options.spawnOptions || {}) };
352
+
353
+ return new Promise((resolve) => {
354
+ let child;
355
+ let settled = false;
356
+ let timeout;
357
+ let cleanupTimeout;
358
+ const baseResult = {
359
+ command: commandLabel,
360
+ phase,
361
+ code: null,
362
+ signal: null,
363
+ timedOut: false,
364
+ cleanupTimedOut: false,
365
+ errorReason: null,
366
+ errorCode: null,
367
+ retryAttempt,
368
+ optional,
369
+ reasonCode: null,
370
+ };
371
+
372
+ const settle = (patch = {}) => {
373
+ if (settled) return;
374
+ settled = true;
375
+ if (timeout) clearTimeout(timeout);
376
+ if (cleanupTimeout) clearTimeout(cleanupTimeout);
377
+ const result = { ...baseResult, ...patch };
378
+ result.reasonCode = result.reasonCode || classifyChildResult(result, { optional });
379
+ if (child) children.delete(child);
380
+ resolve(result);
381
+ };
382
+
383
+ try {
384
+ child = spawnFn(command, args, spawnOptions);
385
+ } catch (error) {
386
+ settle({ errorReason: 'spawn-error', errorCode: sanitizeErrorCode(error) });
387
+ return;
388
+ }
389
+
390
+ if (!child || typeof child.once !== 'function') {
391
+ settle({ errorReason: 'spawn-error', errorCode: 'invalid-child-process' });
392
+ return;
393
+ }
394
+
395
+ children.add(child);
396
+
397
+ timeout = setTimeout(() => {
398
+ baseResult.timedOut = true;
399
+ killChild(child, killSignal);
400
+ cleanupTimeout = setTimeout(() => {
401
+ settle({ timedOut: true, cleanupTimedOut: true, signal: killSignal });
402
+ }, cleanupTimeoutMs);
403
+ if (runtime.unrefTimers !== false && typeof cleanupTimeout.unref === 'function') cleanupTimeout.unref();
404
+ }, timeoutMs);
405
+ if (runtime.unrefTimers !== false && typeof timeout.unref === 'function') timeout.unref();
406
+
407
+ child.once('error', (error) => {
408
+ settle({ errorReason: 'spawn-error', errorCode: sanitizeErrorCode(error) });
409
+ });
410
+
411
+ child.once('close', (code, signal) => {
412
+ settle({
413
+ code: code ?? null,
414
+ signal: signal ?? null,
415
+ timedOut: baseResult.timedOut,
416
+ });
417
+ });
418
+ });
419
+ }
420
+
421
+ function isGlobalInstall() {
422
+ // npm sets npm_config_global=true for global installs
423
+ if (process.env.npm_config_global === 'true') return true;
424
+ // Fallback: check if our location is in a global prefix
425
+ try {
426
+ const globalPrefix = process.env.npm_config_prefix || '';
427
+ if (globalPrefix && __dirname.startsWith(globalPrefix)) return true;
428
+ } catch { /* ignore */ }
429
+ return false;
430
+ }
431
+
432
+ function showUsageMessage(runtime = {}) {
433
+ const logger = runtime.console || console;
434
+ logger.log('\nNeocortex instalado!\n');
435
+ logger.log('Uso:');
436
+ logger.log(' @neocortex @docs/stories/1.1.story.md');
437
+ logger.log(' @neocortex @epic-1');
438
+ logger.log(' @neocortex *status\n');
439
+
440
+ // Story 32.09: Force stub refresh after successful install
441
+ if (runtime.forceStubRefresh) runtime.forceStubRefresh();
442
+ else forceStubRefresh();
443
+
444
+ // Story 32.07: Check server compatibility (fire-and-forget)
445
+ if (runtime.checkServerCompatibility) runtime.checkServerCompatibility();
446
+ else checkServerCompatibility();
447
+ }
448
+
449
+ function showErrorMessage(result, runtime = {}) {
450
+ const logger = runtime.console || console;
451
+ if (result?.reasonCode) emitPublicDiagnostic(result, runtime);
452
+ const reasonCode = result?.reasonCode || classifyChildResult(result || {});
453
+ for (const line of getSanitizedTroubleshootingText(reasonCode)) {
454
+ logger.error(line);
455
+ }
456
+ logger.error('\n[x] Neocortex installation failed.\n');
457
+ logger.error('Troubleshooting:');
458
+ logger.error(' 1. Try again: npm install -g @ornexus/neocortex');
459
+ logger.error(' 2. Check file permissions in your home directory');
460
+ logger.error(' 3. Report at: https://neocortex.sh/support\n');
461
+ }
462
+
463
+ async function runInstaller(runtime = {}) {
464
+ const osRuntime = runtime.os || os;
465
+ const fsRuntime = runtime.fs || fs;
466
+ const env = runtime.env || process.env;
467
+ const logger = runtime.console || console;
468
+ const platform = runtime.platform || osRuntime.platform();
469
+ const timeouts = {
470
+ ...getPostinstallTimeouts(env),
471
+ ...(runtime.timeouts || {}),
472
+ };
473
+
474
+ // Epic 64: Check NEOCORTEX_DEBUG env var for debug mode
475
+ const debugMode = env.NEOCORTEX_DEBUG === '1';
476
+
477
+ if (platform === 'win32') {
478
+ // Windows: run install.ps1
479
+ const scriptPath = path.join(__dirname, 'install.ps1');
480
+ if (!fsRuntime.existsSync(scriptPath)) {
481
+ showUsageMessage(runtime);
482
+ return;
483
+ }
484
+
485
+ const baseFlags = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath];
486
+ const quietFlags = ['-Yes', '-Quiet', '-SkipProject'];
487
+ const retryFlags = ['-Yes', '-SkipProject'];
488
+ if (debugMode) {
489
+ quietFlags.push('-Debug');
490
+ retryFlags.push('-Debug');
491
+ }
492
+
493
+ const shells = ['pwsh', 'powershell'];
494
+ let hasRetried = false;
495
+
496
+ async function retryWithoutQuiet(shellCmd) {
497
+ if (hasRetried) {
498
+ showErrorMessage({
499
+ phase: 'windows-retry-exhausted',
500
+ code: null,
501
+ signal: null,
502
+ timedOut: false,
503
+ retryAttempt: 1,
504
+ reasonCode: 'P177_CHILD_RETRY_EXHAUSTED',
505
+ }, runtime);
506
+ return;
507
+ }
508
+ hasRetried = true;
509
+ logger.log('\nInstalacao falhou. Re-executando com output detalhado...\n');
510
+ const retryResult = await runBoundedChild(shellCmd, [...baseFlags, ...retryFlags], {
511
+ phase: 'windows-retry',
512
+ retryAttempt: 1,
513
+ timeoutMs: timeouts.retryMs,
514
+ cleanupTimeoutMs: timeouts.cleanupMs,
515
+ spawnOptions: { stdio: 'inherit', shell: false },
516
+ }, runtime);
517
+ if (isSuccessfulChildResult(retryResult)) {
518
+ showUsageMessage(runtime);
519
+ } else {
520
+ showErrorMessage({ ...retryResult, reasonCode: 'P177_CHILD_RETRY_EXHAUSTED' }, runtime);
521
+ }
522
+ }
523
+
524
+ async function tryShell(index) {
525
+ if (index >= shells.length) {
526
+ // Epic 65: Don't show "Neocortex instalado!" when no shell was found
527
+ logger.error('\n[!] PowerShell nao encontrado (pwsh ou powershell).');
528
+ logger.error(' Instale manualmente: npx @ornexus/neocortex\n');
529
+ emitPublicDiagnostic({
530
+ phase: 'windows-shell-dispatch',
531
+ code: null,
532
+ signal: null,
533
+ timedOut: false,
534
+ retryAttempt: 0,
535
+ reasonCode: 'P177_MANDATORY_INSTALL_FAILED',
536
+ errorCode: 'powershell-not-found',
537
+ }, runtime);
538
+ return;
539
+ }
540
+ const result = await runBoundedChild(shells[index], [...baseFlags, ...quietFlags], {
541
+ phase: 'windows-initial',
542
+ timeoutMs: timeouts.initialMs,
543
+ cleanupTimeoutMs: timeouts.cleanupMs,
544
+ spawnOptions: { stdio: 'inherit', shell: false },
545
+ }, runtime);
546
+
547
+ if (result.errorReason) {
548
+ await tryShell(index + 1);
549
+ return;
550
+ }
551
+
552
+ if (isSuccessfulChildResult(result)) {
553
+ showUsageMessage(runtime);
554
+ } else {
555
+ await retryWithoutQuiet(shells[index]);
556
+ }
557
+ }
558
+ await tryShell(0);
559
+ } else {
560
+ // Unix: run install.sh
561
+ const scriptPath = path.join(__dirname, 'install.sh');
562
+ if (!fsRuntime.existsSync(scriptPath)) {
563
+ showUsageMessage(runtime);
564
+ return;
565
+ }
566
+
567
+ try { fsRuntime.chmodSync(scriptPath, '755'); } catch { /* ignore */ }
568
+
569
+ const quietArgs = [scriptPath, '--yes', '--quiet', '--skip-project'];
570
+ const retryArgs = [scriptPath, '--yes', '--skip-project'];
571
+ if (debugMode) {
572
+ quietArgs.push('--debug');
573
+ retryArgs.push('--debug');
574
+ }
575
+ let hasRetried = false;
576
+
577
+ async function retryUnixWithoutQuiet(shellCmd) {
578
+ if (hasRetried) {
579
+ showErrorMessage({
580
+ phase: 'unix-retry-exhausted',
581
+ code: null,
582
+ signal: null,
583
+ timedOut: false,
584
+ retryAttempt: 1,
585
+ reasonCode: 'P177_CHILD_RETRY_EXHAUSTED',
586
+ }, runtime);
587
+ return;
588
+ }
589
+ hasRetried = true;
590
+ logger.log('\nInstalacao falhou. Re-executando com output detalhado...\n');
591
+ const retryResult = await runBoundedChild(shellCmd, retryArgs, {
592
+ phase: 'unix-retry',
593
+ retryAttempt: 1,
594
+ timeoutMs: timeouts.retryMs,
595
+ cleanupTimeoutMs: timeouts.cleanupMs,
596
+ spawnOptions: { stdio: 'inherit', shell: false },
597
+ }, runtime);
598
+ if (isSuccessfulChildResult(retryResult)) {
599
+ showUsageMessage(runtime);
600
+ } else {
601
+ showErrorMessage({ ...retryResult, reasonCode: 'P177_CHILD_RETRY_EXHAUSTED' }, runtime);
602
+ }
603
+ }
604
+
605
+ async function tryUnixShell(shellCmd, fallbackShellCmd) {
606
+ const result = await runBoundedChild(shellCmd, quietArgs, {
607
+ phase: 'unix-initial',
608
+ timeoutMs: timeouts.initialMs,
609
+ cleanupTimeoutMs: timeouts.cleanupMs,
610
+ spawnOptions: { stdio: 'inherit', shell: false },
611
+ }, runtime);
612
+
613
+ if (result.errorReason && fallbackShellCmd) {
614
+ const fallbackResult = await runBoundedChild(fallbackShellCmd, quietArgs, {
615
+ phase: 'unix-fallback',
616
+ timeoutMs: timeouts.initialMs,
617
+ cleanupTimeoutMs: timeouts.cleanupMs,
618
+ spawnOptions: { stdio: 'inherit', shell: false },
619
+ }, runtime);
620
+ if (fallbackResult.errorReason) {
621
+ showErrorMessage(fallbackResult, runtime);
622
+ } else if (isSuccessfulChildResult(fallbackResult)) {
623
+ showUsageMessage(runtime);
624
+ } else {
625
+ await retryUnixWithoutQuiet(fallbackShellCmd);
626
+ }
627
+ return;
628
+ }
629
+
630
+ if (isSuccessfulChildResult(result)) {
631
+ showUsageMessage(runtime);
632
+ } else {
633
+ await retryUnixWithoutQuiet(shellCmd);
634
+ }
635
+ }
636
+
637
+ await tryUnixShell('bash', 'sh');
638
+ }
639
+ }
640
+
641
+ /**
642
+ * Story 32.09: Force stub refresh by deleting .version files from target directories.
643
+ * This ensures next invoke detects version mismatch and copies updated stubs.
644
+ * Fire-and-forget, fail-open.
645
+ */
646
+ function forceStubRefresh() {
647
+ try {
648
+ const homeDir = os.homedir();
649
+ const targets = [
650
+ path.join(homeDir, '.claude', 'agents', 'neocortex', '.version'),
651
+ path.join(homeDir, '.cursor', 'agents', '.version'),
652
+ path.join(homeDir, '.gemini', 'agents', '.version'),
653
+ path.join(homeDir, '.codex', '.version'),
654
+ path.join(homeDir, '.codex', 'agents', '.version'),
655
+ path.join(homeDir, '.vscode', '.version'),
656
+ path.join(homeDir, '.agent', 'skills', 'neocortex', '.version'),
657
+ ];
658
+
659
+ for (const versionFile of targets) {
660
+ try {
661
+ if (fs.existsSync(versionFile)) {
662
+ fs.unlinkSync(versionFile);
663
+ }
664
+ } catch { /* ignore per-file errors */ }
665
+ }
666
+ } catch { /* ignore */ }
667
+ }
668
+
669
+ /**
670
+ * Story 32.07: Check server compatibility after install.
671
+ * Informative only -- never blocks. Timeout 5s, all errors ignored.
672
+ */
673
+ function checkServerCompatibility() {
674
+ try {
675
+ const https = require('https');
676
+ let clientVersion;
677
+ try {
678
+ const pkg = require('./package.json');
679
+ clientVersion = pkg.version;
680
+ } catch { return; }
681
+
682
+ const serverUrl = 'https://api.neocortex.sh/health';
683
+
684
+ const req = https.get(serverUrl, { timeout: 5000 }, (res) => {
685
+ let data = '';
686
+ res.on('data', (chunk) => { data += chunk; });
687
+ res.on('end', () => {
688
+ try {
689
+ const health = JSON.parse(data);
690
+ if (health.minClientVersion && !isVersionAtLeastInline(clientVersion, health.minClientVersion)) {
691
+ console.log('\n[!] Aviso: esta versao do client (' + clientVersion + ') pode nao ser compativel.');
692
+ console.log(' Versao minima do server: ' + health.minClientVersion);
693
+ console.log(' Atualize: npm install -g @ornexus/neocortex@latest\n');
694
+ }
695
+ } catch { /* ignore */ }
696
+ });
697
+ });
698
+
699
+ req.on('error', () => { /* ignore - network may not be available */ });
700
+ req.on('timeout', () => { req.destroy(); });
701
+ } catch { /* ignore */ }
702
+ }
703
+
704
+ /**
705
+ * Story 32.07: Inline semver comparison (no external deps).
706
+ */
707
+ function isVersionAtLeastInline(version, minVersion) {
708
+ try {
709
+ const parse = (v) => {
710
+ const m = v.replace(/^v/, '').match(/^(\d+)\.(\d+)\.(\d+)/);
711
+ return m ? [parseInt(m[1]), parseInt(m[2]), parseInt(m[3])] : null;
712
+ };
713
+ const v = parse(version);
714
+ const min = parse(minVersion);
715
+ if (!v || !min) return true;
716
+ if (v[0] !== min[0]) return v[0] > min[0];
717
+ if (v[1] !== min[1]) return v[1] > min[1];
718
+ return v[2] >= min[2];
719
+ } catch { return true; }
720
+ }
721
+
722
+ async function main(runtime = {}) {
723
+ try {
724
+ installParentSignalHandlers(runtime);
725
+ if (isGlobalInstall()) {
726
+ await runInstaller(runtime);
727
+ } else {
728
+ showUsageMessage(runtime);
729
+ }
730
+ } catch {
731
+ // NEVER fail npm install
732
+ showUsageMessage(runtime);
733
+ }
734
+ }
735
+
736
+ if (require.main === module) {
737
+ // Always exit 0 for npm lifecycle compatibility.
738
+ process.on('exit', () => { process.exitCode = 0; });
739
+ main();
740
+ }
741
+
742
+ module.exports = {
743
+ buildPublicInstallerDiagnostic,
744
+ classifyChildResult,
745
+ formatPublicInstallerDiagnostic,
746
+ getSanitizedTroubleshootingText,
747
+ getPostinstallTimeouts,
748
+ installParentSignalHandlers,
749
+ isSuccessfulChildResult,
750
+ main,
751
+ runBoundedChild,
752
+ runInstaller,
753
+ terminateLiveChildren,
754
+ };