target-supabase-sdk 0.2.12 → 0.2.14

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/dist/browser.d.ts +1 -1
  2. package/dist/browser.d.ts.map +1 -1
  3. package/dist/browser.js +1 -1
  4. package/dist/chunks/enable-C7lFooTG.js +874 -0
  5. package/dist/chunks/enable-C7lFooTG.js.map +1 -0
  6. package/dist/chunks/list.api-BzbTJBsM.js.map +1 -1
  7. package/dist/chunks/{task-queue-H4mpSW8R.js → task-queue-qSnsfiIg.js} +111 -4
  8. package/dist/chunks/task-queue-qSnsfiIg.js.map +1 -0
  9. package/dist/node/env/index.d.ts +1 -1
  10. package/dist/node/env/index.d.ts.map +1 -1
  11. package/dist/node/node-runtime.base.d.ts +14 -1
  12. package/dist/node/node-runtime.base.d.ts.map +1 -1
  13. package/dist/node/node.api.d.ts.map +1 -1
  14. package/dist/node/node.constant.d.ts +3 -0
  15. package/dist/node/node.constant.d.ts.map +1 -0
  16. package/dist/node/node.utils.d.ts +0 -2
  17. package/dist/node/node.utils.d.ts.map +1 -1
  18. package/dist/node/preload/run-service-preload.d.ts.map +1 -1
  19. package/dist/node/preload/service-preload.interface.d.ts +3 -1
  20. package/dist/node/preload/service-preload.interface.d.ts.map +1 -1
  21. package/dist/node/process/managed-child-processes.d.ts.map +1 -1
  22. package/dist/node/readiness/index.d.ts +2 -0
  23. package/dist/node/readiness/index.d.ts.map +1 -1
  24. package/dist/node/{service-guard → readiness}/run-readiness-gate.d.ts +1 -1
  25. package/dist/node/readiness/run-readiness-gate.d.ts.map +1 -0
  26. package/dist/node/readiness/service-ready-gate.d.ts.map +1 -1
  27. package/dist/node/runtime-state/create-service-runtime-state-store.d.ts.map +1 -1
  28. package/dist/node/runtime-state/service-runtime-state.types.d.ts +16 -0
  29. package/dist/node/runtime-state/service-runtime-state.types.d.ts.map +1 -1
  30. package/dist/node/service-guard/index.d.ts +4 -4
  31. package/dist/node/service-guard/index.d.ts.map +1 -1
  32. package/dist/node/service-guard/register-service-guard-runner.d.ts +1 -2
  33. package/dist/node/service-guard/register-service-guard-runner.d.ts.map +1 -1
  34. package/dist/node/service-guard/registry-slot-guard-step.d.ts.map +1 -0
  35. package/dist/node/service-guard/run-service-guard-tick.d.ts.map +1 -1
  36. package/dist/node/service-guard/service-guard-node.d.ts +25 -2
  37. package/dist/node/service-guard/service-guard-node.d.ts.map +1 -1
  38. package/dist/node/service-guard/service-guard.interface.d.ts +25 -10
  39. package/dist/node/service-guard/service-guard.interface.d.ts.map +1 -1
  40. package/dist/node/service-host/claim-registry-slot.d.ts +15 -0
  41. package/dist/node/service-host/claim-registry-slot.d.ts.map +1 -0
  42. package/dist/node/service-host/create-l3-child-launcher.d.ts +38 -0
  43. package/dist/node/service-host/create-l3-child-launcher.d.ts.map +1 -0
  44. package/dist/node/service-host/index.d.ts +2 -4
  45. package/dist/node/service-host/index.d.ts.map +1 -1
  46. package/dist/node/service-host/service-host.d.ts +8 -4
  47. package/dist/node/service-host/service-host.d.ts.map +1 -1
  48. package/dist/node/service-host/single-process-service.d.ts +3 -3
  49. package/dist/node/service-host/single-process-service.d.ts.map +1 -1
  50. package/dist/node.d.ts +17 -10
  51. package/dist/node.d.ts.map +1 -1
  52. package/dist/node.js +927 -119
  53. package/dist/node.js.map +1 -1
  54. package/dist/preload.js +9 -6
  55. package/dist/preload.js.map +1 -1
  56. package/dist/service/index.d.ts +2 -2
  57. package/dist/service/index.d.ts.map +1 -1
  58. package/dist/service/registry.service.d.ts +19 -0
  59. package/dist/service/registry.service.d.ts.map +1 -1
  60. package/dist/shared/log/core/create-logger.d.ts.map +1 -0
  61. package/dist/shared/log/{log-batch.d.ts → core/log-batch.d.ts} +4 -4
  62. package/dist/shared/log/core/log-batch.d.ts.map +1 -0
  63. package/dist/shared/log/core/log-manager.d.ts.map +1 -0
  64. package/dist/shared/log/core/log-min-level.d.ts.map +1 -0
  65. package/dist/shared/log/core/log-scope.d.ts.map +1 -0
  66. package/dist/shared/log/index.d.ts +13 -13
  67. package/dist/shared/log/index.d.ts.map +1 -1
  68. package/dist/shared/log/spool/collector.d.ts +21 -0
  69. package/dist/shared/log/spool/collector.d.ts.map +1 -0
  70. package/dist/shared/log/spool/config.d.ts +7 -0
  71. package/dist/shared/log/spool/config.d.ts.map +1 -0
  72. package/dist/shared/log/spool/coordinator.d.ts +18 -0
  73. package/dist/shared/log/spool/coordinator.d.ts.map +1 -0
  74. package/dist/shared/log/spool/enable.d.ts +23 -0
  75. package/dist/shared/log/spool/enable.d.ts.map +1 -0
  76. package/dist/shared/log/spool/file.d.ts +21 -0
  77. package/dist/shared/log/spool/file.d.ts.map +1 -0
  78. package/dist/shared/log/spool/interface.d.ts +55 -0
  79. package/dist/shared/log/spool/interface.d.ts.map +1 -0
  80. package/dist/shared/log/spool/paths.d.ts +6 -0
  81. package/dist/shared/log/spool/paths.d.ts.map +1 -0
  82. package/dist/shared/log/spool/process-roles.d.ts +17 -0
  83. package/dist/shared/log/spool/process-roles.d.ts.map +1 -0
  84. package/dist/shared/log/spool/register-collect-log-runner.d.ts +15 -0
  85. package/dist/shared/log/spool/register-collect-log-runner.d.ts.map +1 -0
  86. package/dist/shared/log/spool/service-lifecycle.d.ts +13 -0
  87. package/dist/shared/log/spool/service-lifecycle.d.ts.map +1 -0
  88. package/dist/shared/log/spool/writer.d.ts +32 -0
  89. package/dist/shared/log/spool/writer.d.ts.map +1 -0
  90. package/dist/shared/log/{log-persist-batch-id.d.ts → upload/batch-id.d.ts} +3 -3
  91. package/dist/shared/log/upload/batch-id.d.ts.map +1 -0
  92. package/dist/shared/log/upload/env.d.ts +7 -0
  93. package/dist/shared/log/upload/env.d.ts.map +1 -0
  94. package/dist/shared/log/{log-persist-flush.d.ts → upload/flush.d.ts} +3 -3
  95. package/dist/shared/log/upload/flush.d.ts.map +1 -0
  96. package/dist/shared/log/{log-persist-hook.d.ts → upload/hook.d.ts} +2 -2
  97. package/dist/shared/log/upload/hook.d.ts.map +1 -0
  98. package/dist/shared/log/upload/interface.d.ts +33 -0
  99. package/dist/shared/log/upload/interface.d.ts.map +1 -0
  100. package/dist/shared/log/upload/logger.d.ts +22 -0
  101. package/dist/shared/log/upload/logger.d.ts.map +1 -0
  102. package/package.json +1 -1
  103. package/src/browser.ts +1 -0
  104. package/src/node/env/index.ts +0 -4
  105. package/src/node/node-runtime.base.ts +33 -5
  106. package/src/node/node.api.ts +1 -1
  107. package/src/node/node.constant.ts +2 -0
  108. package/src/node/node.utils.ts +2 -2
  109. package/src/node/preload/run-service-preload.ts +11 -6
  110. package/src/node/preload/service-preload.interface.ts +3 -1
  111. package/src/node/process/create-managed-child-processes.ts +1 -1
  112. package/src/node/process/managed-child-processes.ts +8 -1
  113. package/src/node/readiness/index.ts +2 -0
  114. package/src/node/{service-guard → readiness}/run-readiness-gate.ts +2 -2
  115. package/src/node/readiness/service-ready-gate.ts +27 -23
  116. package/src/node/runtime-state/create-service-runtime-state-store.ts +11 -0
  117. package/src/node/runtime-state/service-runtime-state.types.ts +12 -0
  118. package/src/node/service-guard/index.ts +7 -8
  119. package/src/node/service-guard/register-service-guard-runner.ts +0 -2
  120. package/src/node/service-guard/run-service-guard-tick.ts +5 -2
  121. package/src/node/service-guard/service-guard-node.ts +234 -6
  122. package/src/node/service-guard/service-guard.interface.ts +35 -10
  123. package/src/node/service-host/claim-registry-slot.ts +33 -0
  124. package/src/node/service-host/create-l3-child-launcher.ts +157 -0
  125. package/src/node/service-host/index.ts +5 -20
  126. package/src/node/service-host/service-host.ts +33 -21
  127. package/src/node/service-host/single-process-service.ts +10 -20
  128. package/src/node.ts +45 -35
  129. package/src/service/index.ts +3 -0
  130. package/src/service/registry.service.ts +142 -0
  131. package/src/shared/log/README.md +206 -0
  132. package/src/shared/log/{log-batch.ts → core/log-batch.ts} +4 -4
  133. package/src/shared/log/{log-manager.ts → core/log-manager.ts} +3 -3
  134. package/src/shared/log/{log-min-level.ts → core/log-min-level.ts} +1 -1
  135. package/src/shared/log/{log-scope.ts → core/log-scope.ts} +1 -1
  136. package/src/shared/log/index.ts +13 -18
  137. package/src/shared/log/spool/collector.ts +330 -0
  138. package/src/shared/log/spool/config.ts +56 -0
  139. package/src/shared/log/spool/coordinator.ts +55 -0
  140. package/src/shared/log/spool/enable.ts +136 -0
  141. package/src/shared/log/spool/file.ts +75 -0
  142. package/src/shared/log/spool/interface.ts +62 -0
  143. package/src/shared/log/spool/paths.ts +30 -0
  144. package/src/shared/log/spool/process-roles.ts +75 -0
  145. package/src/shared/log/spool/register-collect-log-runner.ts +63 -0
  146. package/src/shared/log/spool/service-lifecycle.ts +35 -0
  147. package/src/shared/log/spool/writer.ts +273 -0
  148. package/src/shared/log/{log-persist-batch-id.ts → upload/batch-id.ts} +2 -2
  149. package/src/shared/log/upload/env.ts +26 -0
  150. package/src/shared/log/{log-persist-flush.ts → upload/flush.ts} +8 -7
  151. package/src/shared/log/{log-persist-hook.ts → upload/hook.ts} +1 -1
  152. package/src/shared/log/upload/interface.ts +38 -0
  153. package/src/shared/log/upload/logger.ts +37 -0
  154. package/dist/chunks/enable-log-persist-Dl55_mv2.js +0 -1674
  155. package/dist/chunks/enable-log-persist-Dl55_mv2.js.map +0 -1
  156. package/dist/chunks/task-queue-H4mpSW8R.js.map +0 -1
  157. package/dist/node/service-guard/run-readiness-gate.d.ts.map +0 -1
  158. package/dist/node/service-host/registry-slot-guard-step.d.ts.map +0 -1
  159. package/dist/shared/log/create-logger.d.ts.map +0 -1
  160. package/dist/shared/log/enable-log-persist.d.ts +0 -28
  161. package/dist/shared/log/enable-log-persist.d.ts.map +0 -1
  162. package/dist/shared/log/log-batch.d.ts.map +0 -1
  163. package/dist/shared/log/log-manager.d.ts.map +0 -1
  164. package/dist/shared/log/log-min-level.d.ts.map +0 -1
  165. package/dist/shared/log/log-persist-batch-id.d.ts.map +0 -1
  166. package/dist/shared/log/log-persist-coordinator.d.ts +0 -37
  167. package/dist/shared/log/log-persist-coordinator.d.ts.map +0 -1
  168. package/dist/shared/log/log-persist-errors.d.ts +0 -4
  169. package/dist/shared/log/log-persist-errors.d.ts.map +0 -1
  170. package/dist/shared/log/log-persist-flush.d.ts.map +0 -1
  171. package/dist/shared/log/log-persist-hook.d.ts.map +0 -1
  172. package/dist/shared/log/log-persist-logger.d.ts +0 -16
  173. package/dist/shared/log/log-persist-logger.d.ts.map +0 -1
  174. package/dist/shared/log/log-persist-registry.d.ts +0 -18
  175. package/dist/shared/log/log-persist-registry.d.ts.map +0 -1
  176. package/dist/shared/log/log-persist.config.d.ts +0 -9
  177. package/dist/shared/log/log-persist.config.d.ts.map +0 -1
  178. package/dist/shared/log/log-persist.d.ts +0 -62
  179. package/dist/shared/log/log-persist.d.ts.map +0 -1
  180. package/dist/shared/log/log-persist.interface.d.ts +0 -132
  181. package/dist/shared/log/log-persist.interface.d.ts.map +0 -1
  182. package/dist/shared/log/log-scope.d.ts.map +0 -1
  183. package/src/shared/log/enable-log-persist.ts +0 -225
  184. package/src/shared/log/log-persist-coordinator.ts +0 -107
  185. package/src/shared/log/log-persist-errors.ts +0 -16
  186. package/src/shared/log/log-persist-logger.ts +0 -61
  187. package/src/shared/log/log-persist-registry.ts +0 -252
  188. package/src/shared/log/log-persist.config.ts +0 -115
  189. package/src/shared/log/log-persist.interface.ts +0 -150
  190. package/src/shared/log/log-persist.ts +0 -822
  191. /package/dist/node/{service-host → service-guard}/registry-slot-guard-step.d.ts +0 -0
  192. /package/dist/shared/log/{create-logger.d.ts → core/create-logger.d.ts} +0 -0
  193. /package/dist/shared/log/{log-manager.d.ts → core/log-manager.d.ts} +0 -0
  194. /package/dist/shared/log/{log-min-level.d.ts → core/log-min-level.d.ts} +0 -0
  195. /package/dist/shared/log/{log-scope.d.ts → core/log-scope.d.ts} +0 -0
  196. /package/src/node/{service-host → service-guard}/registry-slot-guard-step.ts +0 -0
  197. /package/src/shared/log/{create-logger.ts → core/create-logger.ts} +0 -0
@@ -0,0 +1,33 @@
1
+ import type { TargetDraft } from "../../../core.interface";
2
+ import type { List } from "../../../list/list.interface";
3
+ import type { LogEntry } from "../core/log-manager";
4
+ /**
5
+ * `ListDetails.loaderKey` stamped on every persisted log batch (write + read side).
6
+ * Business type: **LogBatch** (transport flush). Pairs with log-service **LogTrace**
7
+ * (`LogTrace.0`) after rekeying by `traceId`.
8
+ */
9
+ export declare const LOG_PERSIST_LOADER_KEY = "LogBatch.0";
10
+ /** Alias for {@link LOG_PERSIST_LOADER_KEY} — preferred when contrasting with LogTrace. */
11
+ export declare const LOG_BATCH_LOADER_KEY = "LogBatch.0";
12
+ /** Legacy transport metadata — fixed `"slow"` for spool uploads; required for downstream decode today. */
13
+ export type LogPersistLane = "fast" | "medium" | "slow";
14
+ export interface LogBatchMeta {
15
+ service: string;
16
+ process: string;
17
+ pid: number;
18
+ lane: LogPersistLane;
19
+ count: number;
20
+ from: number | null;
21
+ to: number | null;
22
+ flushedAt: number;
23
+ idempotencyKey: string;
24
+ }
25
+ export interface BuildLogListDraftInput {
26
+ service: string;
27
+ process: string;
28
+ lane: LogPersistLane;
29
+ idempotencyKey: string;
30
+ entries: LogEntry[];
31
+ }
32
+ export type LogListDraft = TargetDraft<List>;
33
+ //# sourceMappingURL=interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../../src/shared/log/upload/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,eAAyB,CAAC;AAE3D,0GAA0G;AAC1G,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** User-facing / lifecycle logs — may be persisted like normal app logs. */
2
+ export declare const LOG_PERSIST_TOPIC = "log-persist";
3
+ /** Operational logs from the persist pipeline — never re-offered to avoid feedback loops. */
4
+ export declare const LOG_PERSIST_INTERNAL_TOPIC = "log-persist-internal";
5
+ type PipelineLogData = Record<string, unknown>;
6
+ /** Supabase upload path (`postLogBatch`). */
7
+ export declare const persistLogger: {
8
+ debug: (message: string, data?: PipelineLogData) => void;
9
+ info: (message: string, data?: PipelineLogData) => void;
10
+ warn: (message: string, data?: PipelineLogData) => void;
11
+ error: (message: string, data?: PipelineLogData) => void;
12
+ };
13
+ /** File spool writer + collector. */
14
+ export declare const spoolLogger: {
15
+ debug: (message: string, data?: PipelineLogData) => void;
16
+ info: (message: string, data?: PipelineLogData) => void;
17
+ warn: (message: string, data?: PipelineLogData) => void;
18
+ error: (message: string, data?: PipelineLogData) => void;
19
+ };
20
+ export declare function isLogPersistInternalTopic(topic: string | undefined): boolean;
21
+ export {};
22
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../../src/shared/log/upload/logger.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C,6FAA6F;AAC7F,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAoB/C,6CAA6C;AAC7C,eAAO,MAAM,aAAa;qBARD,MAAM,SAAS,eAAe;oBAC/B,MAAM,SAAS,eAAe;oBAC9B,MAAM,SAAS,eAAe;qBAC7B,MAAM,SAAS,eAAe;CAKQ,CAAC;AAEhE,qCAAqC;AACrC,eAAO,MAAM,WAAW;qBAXC,MAAM,SAAS,eAAe;oBAC/B,MAAM,SAAS,eAAe;oBAC9B,MAAM,SAAS,eAAe;qBAC7B,MAAM,SAAS,eAAe;CAQK,CAAC;AAE7D,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE5E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "target-supabase-sdk",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "description": "Supabase client initializer and data access APIs",
5
5
  "license": "MIT",
6
6
  "author": "KyLoc20",
package/src/browser.ts CHANGED
@@ -171,6 +171,7 @@ export {
171
171
  registerServiceAtStartup,
172
172
  registrySlotRuntimePatchFromGuardResult,
173
173
  releaseSystemRegistrySlots,
174
+ releaseSystemRegistrySlotsByServiceId,
174
175
  resetSystemRegistryConfig,
175
176
  resetSystemRegistryConfigSchema,
176
177
  resolveActiveRegistryServiceId,
@@ -7,10 +7,6 @@ export {
7
7
  CLI_PROD_FLAG,
8
8
  envProfileFromProcess,
9
9
  loadEnvFiles,
10
- parseEnvFile,
11
- parseEnvFileContent,
12
- parseEnvLine,
13
- pinEnvProfileFromArgv,
14
10
  resolveDefaultEnvFiles,
15
11
  SERVICE_ENV_PROFILE_ENV_KEY,
16
12
  SERVICE_ENV_PROFILE_PROD,
@@ -12,9 +12,12 @@ import {
12
12
  } from "../shared/log";
13
13
  import { getErrorMessage } from "../shared/utils/error.utils";
14
14
  import { patchChangeNodeStatus, patchNodeHeartBeat, patchStopNode, postRegisterNode } from "./node.api";
15
+ import { LOG_TOPIC_NODE } from "./node.constant";
15
16
  import { NodeStatus } from "./node.interface";
16
17
  import { formatHeartbeat, getRandomInterval } from "./node.utils";
17
18
 
19
+ export { LOG_TOPIC_NODE };
20
+
18
21
  /** 主循环单轮运行时上下文 — 由 start() 创建并向下传递 */
19
22
  export interface NodeLoopContext {
20
23
  loopTraceId: string;
@@ -31,7 +34,6 @@ export interface BaseNodeRuntimeOptions {
31
34
  beforeProcessExit?: () => void | Promise<void>;
32
35
  }
33
36
 
34
- export const LOG_TOPIC_NODE = "node";
35
37
  const LOG_TOPIC_COMMAND = "command";
36
38
  const LOG_TOPIC_PROCESS = "process";
37
39
 
@@ -118,6 +120,25 @@ abstract class BaseNodeRuntime {
118
120
  return getRandomInterval();
119
121
  }
120
122
 
123
+ /**
124
+ * When true, the main loop skips commands and {@link runLoopSteps} (heartbeat only).
125
+ * Used by the L3 guard process while waiting for connectivity to recover.
126
+ */
127
+ protected isSilenced(): boolean {
128
+ return false;
129
+ }
130
+
131
+ /**
132
+ * Consecutive heartbeat failures reached {@link HEARTBEAT_FAILURE_THRESHOLD}.
133
+ * Default: shut down the node. Override to wait for recovery instead of exiting.
134
+ */
135
+ protected async onHealthCheckFailed(_ctx: NodeLoopContext): Promise<void> {
136
+ this.requestShutdown("heartbeat:consecutive-failures");
137
+ }
138
+
139
+ /** Heartbeat succeeded while {@link isSilenced} is true. Default: no-op. */
140
+ protected async onHeartbeatRecovered(_ctx: NodeLoopContext): Promise<void> {}
141
+
121
142
  private getLogNodeId(): string {
122
143
  return this.localNodeId ?? BaseNodeRuntime.NODE_ID_PENDING_ASSIGNMENT;
123
144
  }
@@ -284,7 +305,9 @@ abstract class BaseNodeRuntime {
284
305
  data: { nodeId, loopCount: this.loopCount },
285
306
  });
286
307
  try {
287
- await this.batchCommand(loopCtx);
308
+ if (!this.isSilenced()) {
309
+ await this.batchCommand(loopCtx);
310
+ }
288
311
  if (this.isShuttingDown()) {
289
312
  iterLogger.debug("節點關閉中,跳過本輪剩餘步驟", { topic: LOG_TOPIC_NODE });
290
313
  break;
@@ -294,7 +317,9 @@ abstract class BaseNodeRuntime {
294
317
  iterLogger.debug("節點關閉中,跳過本輪剩餘步驟", { topic: LOG_TOPIC_NODE });
295
318
  break;
296
319
  }
297
- await this.runLoopSteps(loopCtx, heartbeatOk);
320
+ if (!this.isSilenced()) {
321
+ await this.runLoopSteps(loopCtx, heartbeatOk);
322
+ }
298
323
  } catch (error) {
299
324
  iterLogger.critical(`主循環第 ${this.loopCount} 輪遇到未知錯誤`, {
300
325
  topic: LOG_TOPIC_NODE,
@@ -410,11 +435,11 @@ abstract class BaseNodeRuntime {
410
435
  threshold: BaseNodeRuntime.HEARTBEAT_FAILURE_THRESHOLD,
411
436
  };
412
437
  if (failureCount >= BaseNodeRuntime.HEARTBEAT_FAILURE_THRESHOLD) {
413
- logger.critical("連續心跳失敗達上限,準備關閉節點", {
438
+ logger.critical("連續心跳失敗達上限", {
414
439
  topic: LOG_TOPIC_NODE,
415
440
  data: logData,
416
441
  });
417
- this.requestShutdown("heartbeat:consecutive-failures");
442
+ await this.onHealthCheckFailed(ctx);
418
443
  } else {
419
444
  logger.warn("心跳更新失敗", { topic: LOG_TOPIC_NODE, data: logData });
420
445
  }
@@ -422,6 +447,9 @@ abstract class BaseNodeRuntime {
422
447
  }
423
448
 
424
449
  this.consecutiveHeartbeatFailures = 0;
450
+ if (this.isSilenced()) {
451
+ await this.onHeartbeatRecovered(ctx);
452
+ }
425
453
  // Success is the steady state every loop — do not INFO-spam; failures already warn/critical.
426
454
  logger.debug("心跳更新成功", {
427
455
  topic: LOG_TOPIC_NODE,
@@ -2,10 +2,10 @@ import { z } from "zod";
2
2
  import { createTarget, type QueryFilter, updateTargetDetails, validateWithSchema } from "../core.api";
3
3
  import { generateResponse } from "../core.interface";
4
4
  import { createLogger } from "../shared/log";
5
+ import { LOG_TOPIC_NODE } from "./node.constant";
5
6
  import { CategoryNode, type Node, type NodeDetails, NodeStatus } from "./node.interface";
6
7
 
7
8
  const NODE_STATUS_FIELD = "details->>status" as const;
8
- const LOG_TOPIC_NODE = "node";
9
9
 
10
10
  const nodeIdSchema = z.string().trim().min(1);
11
11
  const traceIdSchema = z.string().trim().min(1).optional();
@@ -0,0 +1,2 @@
1
+ /** Shared log topic for Node domain APIs and {@link BaseNodeRuntime}. */
2
+ export const LOG_TOPIC_NODE = "node";
@@ -1,4 +1,4 @@
1
- export const formatTimestamp = (timestamp: number): string => {
1
+ const formatTimestamp = (timestamp: number): string => {
2
2
  return new Intl.DateTimeFormat("zh-CN", {
3
3
  year: "numeric",
4
4
  month: "2-digit",
@@ -11,7 +11,7 @@ export const formatTimestamp = (timestamp: number): string => {
11
11
  }).format(timestamp);
12
12
  };
13
13
 
14
- export const formatRelativeTime = (timestamp: number): string => {
14
+ const formatRelativeTime = (timestamp: number): string => {
15
15
  const now = Date.now();
16
16
  const diff = now - timestamp;
17
17
 
@@ -1,14 +1,15 @@
1
1
  import { resolve } from "node:path";
2
- import { validateLogPersistPreloadEnv } from "../../shared/log/enable-log-persist";
3
- import { logManager } from "../../shared/log/log-manager";
4
- import { resolveLogMinLevel } from "../../shared/log/log-min-level";
5
- import { logPersistEnabledFromEnv } from "../../shared/log/log-persist.config";
2
+ import { logManager } from "../../shared/log/core/log-manager";
3
+ import { resolveLogMinLevel } from "../../shared/log/core/log-min-level";
4
+ import { validateLogSpoolPreloadEnv } from "../../shared/log/spool/enable";
5
+ import { mergeLogSpoolExtraProcessRolesEnv } from "../../shared/log/spool/process-roles";
6
+ import { logSpoolEnabledFromEnv } from "../../shared/log/upload/env";
6
7
  import { loadEnvFiles, pinEnvProfileFromArgv } from "../env/load-env";
7
8
  import { resolveProjectRootByPackageName } from "../env/project-root";
8
9
  import type { ServicePreloadOptions } from "./service-preload.interface";
9
10
 
10
11
  function applyServiceEnvDefaults(projectRoot: string, options: ServicePreloadOptions): void {
11
- if (!logPersistEnabledFromEnv()) {
12
+ if (!logSpoolEnabledFromEnv()) {
12
13
  return;
13
14
  }
14
15
 
@@ -22,6 +23,10 @@ function applyServiceEnvDefaults(projectRoot: string, options: ServicePreloadOpt
22
23
  const relative = options.runtimeDataDirRelative ?? "data/runtime";
23
24
  process.env.RUNTIME_DATA_DIR = resolve(projectRoot, relative);
24
25
  }
26
+
27
+ if (options.logSpoolExtraProcessRoles != null && options.logSpoolExtraProcessRoles.length > 0) {
28
+ mergeLogSpoolExtraProcessRolesEnv(process.env, options.logSpoolExtraProcessRoles);
29
+ }
25
30
  }
26
31
 
27
32
  function applyLogMinLevelFromEnv(options: ServicePreloadOptions): void {
@@ -56,7 +61,7 @@ export function runServicePreload(options: ServicePreloadOptions): void {
56
61
 
57
62
  applyLogMinLevelFromEnv(options);
58
63
 
59
- validateLogPersistPreloadEnv();
64
+ validateLogSpoolPreloadEnv();
60
65
 
61
66
  // TODO: Phase 5 — optional unhandledRejection / uncaughtException formatters
62
67
  // (formerly watch-service preload-diagnostics.mjs)
@@ -1,4 +1,4 @@
1
- import type { LogLevel } from "../../shared/log/log-manager";
1
+ import type { LogLevel } from "../../shared/log/core/log-manager";
2
2
 
3
3
  export interface ServicePreloadOptions {
4
4
  /** `import.meta.url` from the service `scripts/preload.mjs`. */
@@ -17,4 +17,6 @@ export interface ServicePreloadOptions {
17
17
  defaultLogMinLevel?: LogLevel;
18
18
  /** Apply `logManager.setOptions({ minLevel })` from env (default true). */
19
19
  applyLogMinLevel?: boolean;
20
+ /** Extra spool roles beyond main|guard|scheduler|worker (e.g. `chrome-sidecar`). Merged into `LOG_SPOOL_EXTRA_PROCESS_ROLES`. */
21
+ logSpoolExtraProcessRoles?: readonly string[];
20
22
  }
@@ -1,4 +1,4 @@
1
- import { createLogger } from "../../shared/log/create-logger";
1
+ import { createLogger } from "../../shared/log/core/create-logger";
2
2
  import type { ManagedChildProcessesOptions } from "./managed-child-processes";
3
3
  import { ManagedChildProcesses } from "./managed-child-processes";
4
4
 
@@ -1,6 +1,7 @@
1
1
  import type { ChildProcess } from "node:child_process";
2
2
  import { resolve } from "node:path";
3
3
  import type { LoggerWithScope } from "../../shared/log";
4
+ import { resolveLogSpoolSpawnEnvForLabel } from "../../shared/log/spool/enable";
4
5
  import { isChildProcessRunning, spawnTsxChild } from "./process-spawn";
5
6
 
6
7
  export interface ManagedChildProcessesOptions {
@@ -80,12 +81,18 @@ export class ManagedChildProcesses {
80
81
  return { child: existing, created: false };
81
82
  }
82
83
 
84
+ const logSpoolEnv = resolveLogSpoolSpawnEnvForLabel(label);
85
+ const childEnv =
86
+ spawnOptions?.env != null
87
+ ? { ...process.env, ...logSpoolEnv, ...spawnOptions.env }
88
+ : { ...process.env, ...logSpoolEnv };
89
+
83
90
  const child = spawnTsxChild({
84
91
  projectRoot: this.projectRoot,
85
92
  entryScript,
86
93
  preloadModules: this.preloadModules,
87
94
  useTsx: spawnOptions?.useTsx ?? this.defaultUseTsx,
88
- env: spawnOptions?.env != null ? { ...process.env, ...spawnOptions.env } : process.env,
95
+ env: childEnv,
89
96
  });
90
97
 
91
98
  child.on("exit", (code: number | null, signal: NodeJS.Signals | null) => {
@@ -12,6 +12,8 @@ export {
12
12
  createSupabaseReachableCheck,
13
13
  } from "./readiness-checks";
14
14
  export { runReadinessChecks } from "./run-readiness-checks";
15
+ export type { RunReadinessGateInput } from "./run-readiness-gate";
16
+ export { runReadinessGate } from "./run-readiness-gate";
15
17
  export type {
16
18
  ServiceReadyGate,
17
19
  ServiceReadySnapshot,
@@ -1,6 +1,6 @@
1
1
  import type { LoggerWithScope } from "../../shared/log";
2
- import type { ReadinessCheck, ReadinessReport } from "../readiness/readiness.types";
3
- import { runReadinessChecks } from "../readiness/run-readiness-checks";
2
+ import type { ReadinessCheck, ReadinessReport } from "./readiness.types";
3
+ import { runReadinessChecks } from "./run-readiness-checks";
4
4
 
5
5
  export interface RunReadinessGateInput {
6
6
  checks: ReadinessCheck[];
@@ -1,8 +1,5 @@
1
1
  import type { LoggerWithScope } from "../../shared/log";
2
-
3
- function sleep(ms: number): Promise<void> {
4
- return new Promise((resolve) => setTimeout(resolve, ms));
5
- }
2
+ import { pollUntil } from "./poll-until";
6
3
 
7
4
  export interface ServiceReadySnapshot {
8
5
  failed: boolean;
@@ -36,30 +33,37 @@ export async function waitForServiceReady(
36
33
  ): Promise<ServiceReadySnapshot> {
37
34
  const pollMs = options.pollMs ?? 500;
38
35
  const defaultFailureMessage = options.failureMessage ?? "Readiness checks failed";
39
- const deadline = Date.now() + options.timeoutMs;
40
36
  let last: ServiceReadySnapshot = { failed: false, ready: false };
41
37
 
42
- while (Date.now() < deadline) {
43
- last = await gate.read();
44
-
38
+ try {
39
+ await pollUntil({
40
+ timeoutMs: options.timeoutMs,
41
+ intervalMs: pollMs,
42
+ until: async () => {
43
+ last = await gate.read();
44
+ if (last.failed) {
45
+ throw new Error(last.failureMessage ?? defaultFailureMessage);
46
+ }
47
+ return last.ready;
48
+ },
49
+ });
50
+ } catch (error) {
45
51
  if (last.failed) {
46
- throw new Error(last.failureMessage ?? defaultFailureMessage);
52
+ throw error instanceof Error ? error : new Error(defaultFailureMessage);
47
53
  }
48
-
49
- if (last.ready) {
50
- options.logger?.info("service ready", {
51
- topic: "readiness",
52
- data: last.readyDetail ?? {},
53
- });
54
- return last;
54
+ const isPollTimeout = error instanceof Error && error.message.startsWith("pollUntil timeout after");
55
+ if (!isPollTimeout) {
56
+ throw error;
55
57
  }
56
-
57
- await sleep(pollMs);
58
+ const message =
59
+ options.formatTimeoutError?.(last, options.timeoutMs) ??
60
+ `Service ready timeout after ${options.timeoutMs}ms (failed=${last.failed}, ready=${last.ready})`;
61
+ throw new Error(message);
58
62
  }
59
63
 
60
- const message =
61
- options.formatTimeoutError?.(last, options.timeoutMs) ??
62
- `Service ready timeout after ${options.timeoutMs}ms (failed=${last.failed}, ready=${last.ready})`;
63
-
64
- throw new Error(message);
64
+ options.logger?.info("service ready", {
65
+ topic: "readiness",
66
+ data: last.readyDetail ?? {},
67
+ });
68
+ return last;
65
69
  }
@@ -58,11 +58,22 @@ function createDefaultServiceRuntimeState<TExtraSlices extends Record<string, ob
58
58
  lastDecision: null,
59
59
  lastSpawnAt: null,
60
60
  spawnCount: 0,
61
+ mode: "healthy",
62
+ silentEnteredAt: null,
63
+ silentLastHeartbeatAt: null,
64
+ silentBackoffMs: 0,
65
+ silentConsecutiveFailures: 0,
66
+ silentRecoveryAttempt: 0,
67
+ silentEvents: [],
61
68
  };
62
69
  const scheduler: SchedulerRuntimeSlice = {
63
70
  lastTickAt: null,
64
71
  lastPostedCount: 0,
65
72
  lastFired: {},
73
+ pid: null,
74
+ spawnedAt: null,
75
+ ready: false,
76
+ readyAt: null,
66
77
  };
67
78
  const worker: WorkerRuntimeSlice = {
68
79
  pid: null,
@@ -15,12 +15,24 @@ export interface GuardRuntimeSlice {
15
15
  lastDecision: string | null;
16
16
  lastSpawnAt: string | null;
17
17
  spawnCount: number;
18
+ /** `healthy` when omitted (legacy shards). Silent: heartbeat-only wait. Recovering: respawn business nodes. */
19
+ mode: "healthy" | "silent" | "recovering";
20
+ silentEnteredAt: string | null;
21
+ silentLastHeartbeatAt: string | null;
22
+ silentBackoffMs: number;
23
+ silentConsecutiveFailures: number;
24
+ silentRecoveryAttempt: number;
25
+ silentEvents: { at: string; type: string; detail?: string }[];
18
26
  }
19
27
 
20
28
  export interface SchedulerRuntimeSlice {
21
29
  lastTickAt: string | null;
22
30
  lastPostedCount: number;
23
31
  lastFired: Record<string, string>;
32
+ pid: number | null;
33
+ spawnedAt: string | null;
34
+ ready: boolean;
35
+ readyAt: string | null;
24
36
  }
25
37
 
26
38
  export interface WorkerRuntimeSlice {
@@ -1,6 +1,9 @@
1
1
  export { registerServiceGuardRunner } from "./register-service-guard-runner";
2
- export type { RunReadinessGateInput } from "./run-readiness-gate";
3
- export { runReadinessGate } from "./run-readiness-gate";
2
+ export type {
3
+ ApplyRegistrySlotGuardInput,
4
+ ApplyRegistrySlotGuardResult,
5
+ } from "./registry-slot-guard-step";
6
+ export { applyRegistrySlotGuardStep } from "./registry-slot-guard-step";
4
7
  export { runServiceGuardTick } from "./run-service-guard-tick";
5
8
  export type {
6
9
  RegisterServiceGuardRunnerOptions,
@@ -8,10 +11,6 @@ export type {
8
11
  ServiceGuardTickInput,
9
12
  ServiceGuardTickResult,
10
13
  } from "./service-guard.interface";
11
- export { SERVICE_GUARD_RUNNER_KEY } from "./service-guard.interface";
14
+ export { guardRetryAfterSec, isGuardAvailable, SERVICE_GUARD_RUNNER_KEY } from "./service-guard.interface";
12
15
  export { ServiceGuardNode } from "./service-guard-node";
13
- export {
14
- getWorkerSpawnCooldownLastAt,
15
- markWorkerSpawned,
16
- resetWorkerSpawnCooldownForTests,
17
- } from "./worker-spawn-cooldown";
16
+ export { markWorkerSpawned } from "./worker-spawn-cooldown";
@@ -60,5 +60,3 @@ export function registerServiceGuardRunner(options: RegisterServiceGuardRunnerOp
60
60
  fn: (ctx) => runServiceGuardRunner(ctx, options),
61
61
  });
62
62
  }
63
-
64
- export { SERVICE_GUARD_RUNNER_KEY };
@@ -1,5 +1,8 @@
1
- import { CategoryNode, evaluateBusyNodeLiveness, type Node, patchServiceRuntime, scanTargetList } from "../../browser";
2
- import { applyRegistrySlotGuardStep } from "../service-host/registry-slot-guard-step";
1
+ import { scanTargetList } from "../../core.api";
2
+ import { patchServiceRuntime } from "../../service/registry.service";
3
+ import { CategoryNode, type Node } from "../node.interface";
4
+ import { evaluateBusyNodeLiveness } from "../node-liveness";
5
+ import { applyRegistrySlotGuardStep } from "./registry-slot-guard-step";
3
6
  import type { ServiceGuardTickInput, ServiceGuardTickResult } from "./service-guard.interface";
4
7
  import { getWorkerSpawnCooldownLastAt, markWorkerSpawned } from "./worker-spawn-cooldown";
5
8