instar 0.28.102 → 0.28.103

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 (247) hide show
  1. package/.claude/hooks/instar/before-prompt-recall.js +90 -0
  2. package/dist/cli.js +28 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/init.d.ts +1 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +14 -1
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/jobMigrate.d.ts +46 -0
  9. package/dist/commands/jobMigrate.d.ts.map +1 -0
  10. package/dist/commands/jobMigrate.js +292 -0
  11. package/dist/commands/jobMigrate.js.map +1 -0
  12. package/dist/commands/server.d.ts.map +1 -1
  13. package/dist/commands/server.js +88 -42
  14. package/dist/commands/server.js.map +1 -1
  15. package/dist/core/BackupManager.d.ts +27 -1
  16. package/dist/core/BackupManager.d.ts.map +1 -1
  17. package/dist/core/BackupManager.js +56 -1
  18. package/dist/core/BackupManager.js.map +1 -1
  19. package/dist/core/GitStateManager.d.ts +8 -0
  20. package/dist/core/GitStateManager.d.ts.map +1 -1
  21. package/dist/core/GitStateManager.js +31 -1
  22. package/dist/core/GitStateManager.js.map +1 -1
  23. package/dist/core/MigratorStepEngine.d.ts +170 -0
  24. package/dist/core/MigratorStepEngine.d.ts.map +1 -0
  25. package/dist/core/MigratorStepEngine.js +352 -0
  26. package/dist/core/MigratorStepEngine.js.map +1 -0
  27. package/dist/core/PostUpdateMigrator.d.ts +76 -0
  28. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  29. package/dist/core/PostUpdateMigrator.js +252 -1
  30. package/dist/core/PostUpdateMigrator.js.map +1 -1
  31. package/dist/core/PreCompactionFlush.d.ts +101 -0
  32. package/dist/core/PreCompactionFlush.d.ts.map +1 -0
  33. package/dist/core/PreCompactionFlush.js +282 -0
  34. package/dist/core/PreCompactionFlush.js.map +1 -0
  35. package/dist/core/PromptBuildRecall.d.ts +97 -0
  36. package/dist/core/PromptBuildRecall.d.ts.map +1 -0
  37. package/dist/core/PromptBuildRecall.js +152 -0
  38. package/dist/core/PromptBuildRecall.js.map +1 -0
  39. package/dist/core/selectIntelligenceProvider.d.ts +41 -0
  40. package/dist/core/selectIntelligenceProvider.d.ts.map +1 -0
  41. package/dist/core/selectIntelligenceProvider.js +89 -0
  42. package/dist/core/selectIntelligenceProvider.js.map +1 -0
  43. package/dist/lifeline/ServerSupervisor.d.ts +183 -0
  44. package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
  45. package/dist/lifeline/ServerSupervisor.js +443 -0
  46. package/dist/lifeline/ServerSupervisor.js.map +1 -1
  47. package/dist/memory/NativeModuleHealer.d.ts +89 -0
  48. package/dist/memory/NativeModuleHealer.d.ts.map +1 -1
  49. package/dist/memory/NativeModuleHealer.js +371 -1
  50. package/dist/memory/NativeModuleHealer.js.map +1 -1
  51. package/dist/memory/SemanticMemory.d.ts +131 -0
  52. package/dist/memory/SemanticMemory.d.ts.map +1 -1
  53. package/dist/memory/SemanticMemory.js +315 -0
  54. package/dist/memory/SemanticMemory.js.map +1 -1
  55. package/dist/messaging/DeliveryRetryManager.d.ts +60 -0
  56. package/dist/messaging/DeliveryRetryManager.d.ts.map +1 -1
  57. package/dist/messaging/DeliveryRetryManager.js +104 -0
  58. package/dist/messaging/DeliveryRetryManager.js.map +1 -1
  59. package/dist/monitoring/DegradationReporter.d.ts +164 -0
  60. package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
  61. package/dist/monitoring/DegradationReporter.js +309 -1
  62. package/dist/monitoring/DegradationReporter.js.map +1 -1
  63. package/dist/monitoring/ErrorCodeExtractor.d.ts +69 -0
  64. package/dist/monitoring/ErrorCodeExtractor.d.ts.map +1 -0
  65. package/dist/monitoring/ErrorCodeExtractor.js +131 -0
  66. package/dist/monitoring/ErrorCodeExtractor.js.map +1 -0
  67. package/dist/monitoring/PromptGate.d.ts +34 -0
  68. package/dist/monitoring/PromptGate.d.ts.map +1 -1
  69. package/dist/monitoring/PromptGate.js +81 -1
  70. package/dist/monitoring/PromptGate.js.map +1 -1
  71. package/dist/monitoring/Redactor.d.ts +58 -0
  72. package/dist/monitoring/Redactor.d.ts.map +1 -0
  73. package/dist/monitoring/Redactor.js +143 -0
  74. package/dist/monitoring/Redactor.js.map +1 -0
  75. package/dist/monitoring/probes/LifelineProbe.d.ts +7 -0
  76. package/dist/monitoring/probes/LifelineProbe.d.ts.map +1 -1
  77. package/dist/monitoring/probes/LifelineProbe.js +7 -0
  78. package/dist/monitoring/probes/LifelineProbe.js.map +1 -1
  79. package/dist/monitoring/probes/__shared.d.ts +50 -0
  80. package/dist/monitoring/probes/__shared.d.ts.map +1 -0
  81. package/dist/monitoring/probes/__shared.js +51 -0
  82. package/dist/monitoring/probes/__shared.js.map +1 -0
  83. package/dist/remediation/IntentJournal.d.ts +64 -0
  84. package/dist/remediation/IntentJournal.d.ts.map +1 -0
  85. package/dist/remediation/IntentJournal.js +118 -0
  86. package/dist/remediation/IntentJournal.js.map +1 -0
  87. package/dist/remediation/MachineLock.d.ts +137 -0
  88. package/dist/remediation/MachineLock.d.ts.map +1 -0
  89. package/dist/remediation/MachineLock.js +314 -0
  90. package/dist/remediation/MachineLock.js.map +1 -0
  91. package/dist/remediation/PrimaryAggregatorLease.d.ts +205 -0
  92. package/dist/remediation/PrimaryAggregatorLease.d.ts.map +1 -0
  93. package/dist/remediation/PrimaryAggregatorLease.js +450 -0
  94. package/dist/remediation/PrimaryAggregatorLease.js.map +1 -0
  95. package/dist/remediation/RemediationContext.d.ts +63 -0
  96. package/dist/remediation/RemediationContext.d.ts.map +1 -0
  97. package/dist/remediation/RemediationContext.js +109 -0
  98. package/dist/remediation/RemediationContext.js.map +1 -0
  99. package/dist/remediation/RemediationKeyVault.d.ts +123 -0
  100. package/dist/remediation/RemediationKeyVault.d.ts.map +1 -0
  101. package/dist/remediation/RemediationKeyVault.js +564 -0
  102. package/dist/remediation/RemediationKeyVault.js.map +1 -0
  103. package/dist/remediation/Remediator.d.ts +288 -0
  104. package/dist/remediation/Remediator.d.ts.map +1 -0
  105. package/dist/remediation/Remediator.js +520 -0
  106. package/dist/remediation/Remediator.js.map +1 -0
  107. package/dist/remediation/RemediatorBootstrap.d.ts +141 -0
  108. package/dist/remediation/RemediatorBootstrap.d.ts.map +1 -0
  109. package/dist/remediation/RemediatorBootstrap.js +255 -0
  110. package/dist/remediation/RemediatorBootstrap.js.map +1 -0
  111. package/dist/remediation/TrustElevationSource.d.ts +153 -0
  112. package/dist/remediation/TrustElevationSource.d.ts.map +1 -0
  113. package/dist/remediation/TrustElevationSource.js +208 -0
  114. package/dist/remediation/TrustElevationSource.js.map +1 -0
  115. package/dist/remediation/audit/AuditProjection.d.ts +37 -0
  116. package/dist/remediation/audit/AuditProjection.d.ts.map +1 -0
  117. package/dist/remediation/audit/AuditProjection.js +118 -0
  118. package/dist/remediation/audit/AuditProjection.js.map +1 -0
  119. package/dist/remediation/audit/AuditWriter.d.ts +79 -0
  120. package/dist/remediation/audit/AuditWriter.d.ts.map +1 -0
  121. package/dist/remediation/audit/AuditWriter.js +132 -0
  122. package/dist/remediation/audit/AuditWriter.js.map +1 -0
  123. package/dist/remediation/channels/CliApprovalChannel.d.ts +37 -0
  124. package/dist/remediation/channels/CliApprovalChannel.d.ts.map +1 -0
  125. package/dist/remediation/channels/CliApprovalChannel.js +45 -0
  126. package/dist/remediation/channels/CliApprovalChannel.js.map +1 -0
  127. package/dist/remediation/channels/TelegramApprovalChannel.d.ts +37 -0
  128. package/dist/remediation/channels/TelegramApprovalChannel.d.ts.map +1 -0
  129. package/dist/remediation/channels/TelegramApprovalChannel.js +45 -0
  130. package/dist/remediation/channels/TelegramApprovalChannel.js.map +1 -0
  131. package/dist/remediation/runbooks/db-corruption.d.ts +86 -0
  132. package/dist/remediation/runbooks/db-corruption.d.ts.map +1 -0
  133. package/dist/remediation/runbooks/db-corruption.js +190 -0
  134. package/dist/remediation/runbooks/db-corruption.js.map +1 -0
  135. package/dist/remediation/runbooks/messaging-delivery-failed.d.ts +108 -0
  136. package/dist/remediation/runbooks/messaging-delivery-failed.d.ts.map +1 -0
  137. package/dist/remediation/runbooks/messaging-delivery-failed.js +172 -0
  138. package/dist/remediation/runbooks/messaging-delivery-failed.js.map +1 -0
  139. package/dist/remediation/runbooks/node-abi-mismatch.d.ts +70 -0
  140. package/dist/remediation/runbooks/node-abi-mismatch.d.ts.map +1 -0
  141. package/dist/remediation/runbooks/node-abi-mismatch.js +216 -0
  142. package/dist/remediation/runbooks/node-abi-mismatch.js.map +1 -0
  143. package/dist/remediation/runbooks/supervisor-preflight.d.ts +114 -0
  144. package/dist/remediation/runbooks/supervisor-preflight.d.ts.map +1 -0
  145. package/dist/remediation/runbooks/supervisor-preflight.js +299 -0
  146. package/dist/remediation/runbooks/supervisor-preflight.js.map +1 -0
  147. package/dist/scheduler/AgentMdAtomicSave.d.ts +85 -0
  148. package/dist/scheduler/AgentMdAtomicSave.d.ts.map +1 -0
  149. package/dist/scheduler/AgentMdAtomicSave.js +169 -0
  150. package/dist/scheduler/AgentMdAtomicSave.js.map +1 -0
  151. package/dist/scheduler/AgentMdReconcile.d.ts +62 -0
  152. package/dist/scheduler/AgentMdReconcile.d.ts.map +1 -0
  153. package/dist/scheduler/AgentMdReconcile.js +212 -0
  154. package/dist/scheduler/AgentMdReconcile.js.map +1 -0
  155. package/dist/scheduler/DisabledBodyDrift.d.ts +70 -0
  156. package/dist/scheduler/DisabledBodyDrift.d.ts.map +1 -0
  157. package/dist/scheduler/DisabledBodyDrift.js +149 -0
  158. package/dist/scheduler/DisabledBodyDrift.js.map +1 -0
  159. package/dist/scheduler/InstallBuiltinJobs.d.ts +53 -0
  160. package/dist/scheduler/InstallBuiltinJobs.d.ts.map +1 -0
  161. package/dist/scheduler/InstallBuiltinJobs.js +212 -0
  162. package/dist/scheduler/InstallBuiltinJobs.js.map +1 -0
  163. package/dist/scheduler/JobLoader.d.ts.map +1 -1
  164. package/dist/scheduler/JobLoader.js +48 -0
  165. package/dist/scheduler/JobLoader.js.map +1 -1
  166. package/dist/scheduler/MigrationInvariants.d.ts +62 -0
  167. package/dist/scheduler/MigrationInvariants.d.ts.map +1 -0
  168. package/dist/scheduler/MigrationInvariants.js +215 -0
  169. package/dist/scheduler/MigrationInvariants.js.map +1 -0
  170. package/dist/scheduler/MigrationLedger.d.ts +84 -0
  171. package/dist/scheduler/MigrationLedger.d.ts.map +1 -0
  172. package/dist/scheduler/MigrationLedger.js +114 -0
  173. package/dist/scheduler/MigrationLedger.js.map +1 -0
  174. package/dist/server/fileRoutes.d.ts.map +1 -1
  175. package/dist/server/fileRoutes.js +7 -0
  176. package/dist/server/fileRoutes.js.map +1 -1
  177. package/dist/server/routes.d.ts.map +1 -1
  178. package/dist/server/routes.js +141 -0
  179. package/dist/server/routes.js.map +1 -1
  180. package/package.json +3 -2
  181. package/scripts/classify-default-drift.mjs +238 -0
  182. package/scripts/eli16-overview-check.mjs +85 -0
  183. package/scripts/instar-dev-precommit.js +60 -1
  184. package/scripts/lint-degradation-emit-sites.js +116 -0
  185. package/scripts/lint-no-direct-destructive.js +12 -0
  186. package/scripts/protect-migration-guarantee.js +61 -0
  187. package/scripts/regen-default-job-templates.mjs +111 -0
  188. package/scripts/verify-runbook-pr-signature.js +366 -0
  189. package/src/data/builtin-manifest.json +93 -93
  190. package/src/scaffold/bootstrap.ts +138 -0
  191. package/src/scaffold/keys/instar-release-pub.pem +3 -0
  192. package/src/scaffold/templates/jobs/instar/.gitkeep +0 -0
  193. package/src/scaffold/templates/jobs/instar/commitment-detection.md +28 -0
  194. package/src/scaffold/templates/jobs/instar/evolution-overdue-check.md +28 -0
  195. package/src/scaffold/templates/jobs/instar/evolution-proposal-evaluate.md +30 -0
  196. package/src/scaffold/templates/jobs/instar/evolution-proposal-implement.md +25 -0
  197. package/src/scaffold/templates/jobs/instar/health-check.md +14 -0
  198. package/src/scaffold/templates/jobs/instar/identity-review.md +42 -0
  199. package/src/scaffold/templates/jobs/instar/insight-harvest.md +31 -0
  200. package/src/scaffold/templates/jobs/instar/overseer-development.md +23 -0
  201. package/src/scaffold/templates/jobs/instar/overseer-guardian.md +28 -0
  202. package/src/scaffold/templates/jobs/instar/overseer-infrastructure.md +26 -0
  203. package/src/scaffold/templates/jobs/instar/overseer-learning.md +28 -0
  204. package/src/scaffold/templates/jobs/instar/overseer-maintenance.md +27 -0
  205. package/src/scaffold/templates/jobs/instar/reflection-trigger.md +40 -0
  206. package/src/scaffold/templates/jobs/instar/relationship-maintenance.md +16 -0
  207. package/src/scaffold/templates.ts +1616 -0
  208. package/upgrades/0.28.102.md +6 -7
  209. package/upgrades/0.28.103.md +471 -0
  210. package/upgrades/side-effects/a47-primary-aggregator-lease.md +82 -0
  211. package/upgrades/side-effects/agentmd-atomic-save.md +66 -0
  212. package/upgrades/side-effects/agentmd-loader-200jobs-perf-benchmark.md +50 -0
  213. package/upgrades/side-effects/agentmd-reconcile-boot-lifecycle.md +66 -0
  214. package/upgrades/side-effects/api-safety-guard.md +80 -0
  215. package/upgrades/side-effects/c1-runbook-pr-gate.md +83 -0
  216. package/upgrades/side-effects/disabled-body-drift-detection.md +59 -0
  217. package/upgrades/side-effects/drift-classifier-release-time.md +71 -0
  218. package/upgrades/side-effects/eli16-overview-required-gate.md +77 -0
  219. package/upgrades/side-effects/f1-remediation-key-vault.md +195 -0
  220. package/upgrades/side-effects/f2-redactor-errorcode-extractor.md +130 -0
  221. package/upgrades/side-effects/f3-degradation-reporter-shim.md +105 -0
  222. package/upgrades/side-effects/f4-machine-locks-intent-journal-audit.md +117 -0
  223. package/upgrades/side-effects/f5-trust-elevation-source.md +258 -0
  224. package/upgrades/side-effects/f6-supervisor-handshake.md +234 -0
  225. package/upgrades/side-effects/f7-post-update-migrator-atomic-step.md +129 -0
  226. package/upgrades/side-effects/f8-remediator-skeleton.md +153 -0
  227. package/upgrades/side-effects/f8-rest-enforcement.md +72 -0
  228. package/upgrades/side-effects/file-viewer-jobs-instar-never-editable.md +41 -0
  229. package/upgrades/side-effects/frontmatter-interpolation-breakout-test.md +48 -0
  230. package/upgrades/side-effects/jobs-as-agentmd-phase-2.md +78 -0
  231. package/upgrades/side-effects/jobs-as-agentmd-phase-3.md +76 -0
  232. package/upgrades/side-effects/jobs-as-agentmd-phase-4-endpoints.md +62 -0
  233. package/upgrades/side-effects/jobs-as-agentmd-phase-5.md +67 -0
  234. package/upgrades/side-effects/jobs-as-agentmd-phase-6.md +53 -0
  235. package/upgrades/side-effects/jobs-endpoints-auth-verification.md +52 -0
  236. package/upgrades/side-effects/migration-guarantee-suite.md +61 -0
  237. package/upgrades/side-effects/migration-runtime-invariant-gate.md +59 -0
  238. package/upgrades/side-effects/migration-telemetry-invariant-8.md +68 -0
  239. package/upgrades/side-effects/npm-pack-templates-smoke.md +51 -0
  240. package/upgrades/side-effects/openclaw-import-before-prompt-build.md +84 -0
  241. package/upgrades/side-effects/openclaw-import-pre-compaction-flush.md +85 -0
  242. package/upgrades/side-effects/prompt-gate-no-prompt-cache.md +258 -0
  243. package/upgrades/side-effects/tier2-degradation-reporter-live-wire.md +146 -0
  244. package/upgrades/side-effects/w1-node-abi-mismatch-runbook.md +154 -0
  245. package/upgrades/side-effects/w2-supervisor-preflight-runbook.md +176 -0
  246. package/upgrades/side-effects/w3-messaging-delivery-failed-runbook.md +185 -0
  247. package/upgrades/side-effects/w4-db-corruption-runbook.md +114 -0
@@ -0,0 +1,352 @@
1
+ /**
2
+ * MigratorStepEngine — atomic-step primitive for post-update migrations.
3
+ *
4
+ * Implements F-7 of `docs/specs/SELF-HEALING-REMEDIATOR-V2-SPEC.md`
5
+ * (§R1 Upgrade invariants + §A35 + §A50 + §A57 Tier-2). Provides:
6
+ *
7
+ * 1. `MigratorStepEngine` — registers named, idempotent, run-once-per-
8
+ * version atomic steps that fire at release boundaries. Each step is
9
+ * self-contained; one step failing does NOT roll back prior steps or
10
+ * prevent subsequent steps from running. Persisted state lives at
11
+ * `<stateDir>/migrator-steps-completed.json` keyed by
12
+ * `<version>:<step-name>`.
13
+ *
14
+ * 2. `AnnouncementManager` — `announceOnce` primitive for "show this
15
+ * message to the user exactly once and then never again". Used for
16
+ * surfacing migration completions, structural changes, or any other
17
+ * one-shot user-facing notice. Persisted state lives at
18
+ * `<stateDir>/announcements-shown.json` keyed by announcementId.
19
+ *
20
+ * Design notes:
21
+ *
22
+ * - Atomic: each step records outcome (completed | skipped | failed)
23
+ * atomically (temp-file → fsync → rename). A crash mid-step leaves
24
+ * the ledger consistent — either the step is recorded or it isn't,
25
+ * never partial.
26
+ *
27
+ * - Version-gated: a step `version: "1.2.3"` runs only when the engine
28
+ * is invoked with `toVersion >= "1.2.3"` (semver compare). Steps for
29
+ * versions strictly newer than `toVersion` are skipped without being
30
+ * recorded — they will run on the next update boundary that catches
31
+ * up to them.
32
+ *
33
+ * - Once-per-version-step pair: a successful step is recorded with key
34
+ * `<version>:<step-name>`. Re-runs of `runPendingSteps()` short-circuit
35
+ * on that key. A FAILED step IS also recorded (with outcome `failed`)
36
+ * so the same broken step doesn't re-run unbounded on every update —
37
+ * operators see the failure in the report and decide whether to retry.
38
+ *
39
+ * - No rollback. Each step must be self-contained and atomic on its
40
+ * own. The spec deliberately rejects step ordering / dependency /
41
+ * rollback semantics — those couplings are what made v1's migrator
42
+ * unmaintainable.
43
+ */
44
+ import fs from 'node:fs';
45
+ import path from 'node:path';
46
+ // ── Semver comparison (minimal, sufficient for this engine) ─────────
47
+ const VERSION_RE = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
48
+ function parseVersion(v) {
49
+ const m = VERSION_RE.exec(v.trim());
50
+ if (!m)
51
+ return null;
52
+ return [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10), m[4] ?? ''];
53
+ }
54
+ /**
55
+ * Compare two semver strings. Returns -1 / 0 / 1. Pre-release strings are
56
+ * compared lexically when major.minor.patch match (good-enough for our
57
+ * "run on version >= X" usage). Unparseable inputs sort as -Infinity so
58
+ * a malformed `fromVersion` never blocks step execution.
59
+ */
60
+ export function compareSemver(a, b) {
61
+ const pa = parseVersion(a);
62
+ const pb = parseVersion(b);
63
+ if (!pa && !pb)
64
+ return 0;
65
+ if (!pa)
66
+ return -1;
67
+ if (!pb)
68
+ return 1;
69
+ for (let i = 0; i < 3; i++) {
70
+ if (pa[i] < pb[i])
71
+ return -1;
72
+ if (pa[i] > pb[i])
73
+ return 1;
74
+ }
75
+ // major.minor.patch equal — compare pre-release. Absent pre-release
76
+ // outranks any pre-release (e.g. 1.0.0 > 1.0.0-rc1).
77
+ const preA = pa[3];
78
+ const preB = pb[3];
79
+ if (preA === '' && preB === '')
80
+ return 0;
81
+ if (preA === '')
82
+ return 1;
83
+ if (preB === '')
84
+ return -1;
85
+ if (preA < preB)
86
+ return -1;
87
+ if (preA > preB)
88
+ return 1;
89
+ return 0;
90
+ }
91
+ // ── MigratorStepEngine ───────────────────────────────────────────────
92
+ export class MigratorStepEngine {
93
+ stateDir;
94
+ steps = [];
95
+ /** Path to the step-completion ledger. */
96
+ ledgerPath;
97
+ constructor(stateDir) {
98
+ this.stateDir = path.resolve(stateDir);
99
+ this.ledgerPath = path.join(this.stateDir, 'migrator-steps-completed.json');
100
+ }
101
+ /**
102
+ * Register an atomic step. Steps run in registration order on each
103
+ * invocation of `runPendingSteps()`, subject to the version gate and
104
+ * the per-version-per-step idempotency guard.
105
+ *
106
+ * Duplicate `name` values are rejected at registration time — names
107
+ * are global identifiers in the ledger.
108
+ */
109
+ registerStep(step) {
110
+ if (!step.name || typeof step.name !== 'string') {
111
+ throw new Error('MigratorStepEngine.registerStep: step.name is required');
112
+ }
113
+ if (!step.version || typeof step.version !== 'string') {
114
+ throw new Error(`MigratorStepEngine.registerStep: step.version is required (step=${step.name})`);
115
+ }
116
+ if (typeof step.run !== 'function') {
117
+ throw new Error(`MigratorStepEngine.registerStep: step.run must be a function (step=${step.name})`);
118
+ }
119
+ for (const existing of this.steps) {
120
+ if (existing.name === step.name) {
121
+ throw new Error(`MigratorStepEngine.registerStep: duplicate step name "${step.name}"`);
122
+ }
123
+ }
124
+ this.steps.push(step);
125
+ }
126
+ /**
127
+ * Run every pending step. A step is "pending" when:
128
+ * - its `version <= toVersion` (semver compare), AND
129
+ * - no ledger entry exists for `<version>:<name>`.
130
+ *
131
+ * Steps for versions strictly newer than `toVersion` are reported as
132
+ * `skipped` (with details: `future-version`) but NOT recorded — they
133
+ * will run on a later update boundary that crosses their threshold.
134
+ *
135
+ * Steps whose ledger entry already exists are reported as `skipped`
136
+ * (with details: `already-recorded:<previous-outcome>`).
137
+ *
138
+ * Each step is executed under a try/catch; thrown errors are converted
139
+ * to `outcome: 'failed'` and recorded. The engine never propagates
140
+ * step failures to the caller — one broken step cannot block subsequent
141
+ * steps.
142
+ */
143
+ async runPendingSteps(fromVersion, toVersion) {
144
+ if (!fs.existsSync(this.stateDir)) {
145
+ fs.mkdirSync(this.stateDir, { recursive: true });
146
+ }
147
+ const ledger = this.readLedger();
148
+ const report = { steps: [] };
149
+ for (const step of this.steps) {
150
+ const key = `${step.version}:${step.name}`;
151
+ // Already recorded — skip.
152
+ if (ledger[key]) {
153
+ report.steps.push({
154
+ name: step.name,
155
+ outcome: 'skipped',
156
+ details: `already-recorded:${ledger[key].outcome}`,
157
+ });
158
+ continue;
159
+ }
160
+ // Future-version — skip without recording.
161
+ if (compareSemver(step.version, toVersion) > 0) {
162
+ report.steps.push({
163
+ name: step.name,
164
+ outcome: 'skipped',
165
+ details: `future-version:${step.version} > ${toVersion}`,
166
+ });
167
+ continue;
168
+ }
169
+ // Execute.
170
+ const ctx = {
171
+ stateDir: this.stateDir,
172
+ fromVersion,
173
+ toVersion,
174
+ logger: (_msg) => {
175
+ /* default no-op; callers wire a real logger via wrapping */
176
+ },
177
+ };
178
+ let result;
179
+ try {
180
+ result = await step.run(ctx);
181
+ if (!result || typeof result.outcome !== 'string') {
182
+ result = { outcome: 'failed', details: 'step returned malformed result' };
183
+ }
184
+ }
185
+ catch (err) {
186
+ const msg = err instanceof Error ? err.message : String(err);
187
+ result = { outcome: 'failed', details: `threw: ${msg}` };
188
+ }
189
+ // Record outcome (including failures — see class docstring).
190
+ ledger[key] = {
191
+ outcome: result.outcome,
192
+ details: result.details,
193
+ recordedAt: new Date().toISOString(),
194
+ };
195
+ this.writeLedger(ledger);
196
+ report.steps.push({
197
+ name: step.name,
198
+ outcome: result.outcome,
199
+ details: result.details,
200
+ });
201
+ }
202
+ return report;
203
+ }
204
+ /**
205
+ * Look up whether `<version>:<name>` is recorded. Returns the ledger
206
+ * entry or `undefined`. Intended for callers that want to render a
207
+ * migration report.
208
+ */
209
+ getRecorded(version, name) {
210
+ const ledger = this.readLedger();
211
+ return ledger[`${version}:${name}`];
212
+ }
213
+ // ── Ledger I/O ─────────────────────────────────────────────────────
214
+ readLedger() {
215
+ try {
216
+ if (!fs.existsSync(this.ledgerPath))
217
+ return {};
218
+ const raw = fs.readFileSync(this.ledgerPath, 'utf-8');
219
+ const parsed = JSON.parse(raw);
220
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
221
+ return parsed;
222
+ }
223
+ return {};
224
+ }
225
+ catch {
226
+ // Corrupt ledger — treat as empty rather than blocking. The crash
227
+ // recovery path is: subsequent run records its results into a
228
+ // fresh ledger. Lost history of past runs is acceptable; blocked
229
+ // upgrades are not.
230
+ return {};
231
+ }
232
+ }
233
+ writeLedger(ledger) {
234
+ const tmpPath = `${this.ledgerPath}.tmp-${process.pid}-${Date.now()}`;
235
+ const serialized = JSON.stringify(ledger, null, 2) + '\n';
236
+ const fd = fs.openSync(tmpPath, 'w', 0o600);
237
+ try {
238
+ fs.writeSync(fd, serialized);
239
+ fs.fsyncSync(fd);
240
+ }
241
+ finally {
242
+ fs.closeSync(fd);
243
+ }
244
+ fs.renameSync(tmpPath, this.ledgerPath);
245
+ }
246
+ }
247
+ /**
248
+ * AnnouncementManager — "show this message to the user once, then never
249
+ * again" primitive. Used for one-shot migration completions, structural-
250
+ * change notices, etc.
251
+ *
252
+ * The default sink writes to stderr with an `[announcement]` prefix.
253
+ * Callers can pass a custom sink (e.g. routed to Telegram or the
254
+ * dashboard's attention queue) via the constructor.
255
+ *
256
+ * Persisted state at `<stateDir>/announcements-shown.json`. The ledger
257
+ * survives across instances and across agent restarts.
258
+ */
259
+ export class AnnouncementManager {
260
+ stateDir;
261
+ ledgerPath;
262
+ sink;
263
+ constructor(stateDir, sink) {
264
+ this.stateDir = path.resolve(stateDir);
265
+ this.ledgerPath = path.join(this.stateDir, 'announcements-shown.json');
266
+ this.sink = sink ?? defaultSink;
267
+ }
268
+ /**
269
+ * Emit the announcement exactly once per `announcementId`.
270
+ *
271
+ * Returns `true` if the announcement was emitted this call; `false`
272
+ * if a prior call (in this process or a previous run) already
273
+ * emitted it.
274
+ *
275
+ * Caller-side idempotency: the ledger is consulted BEFORE the sink
276
+ * is invoked. Repeated calls with the same id are O(1) reads.
277
+ */
278
+ async announceOnce(announcementId, message, channel) {
279
+ if (!announcementId || typeof announcementId !== 'string') {
280
+ throw new Error('AnnouncementManager.announceOnce: announcementId is required');
281
+ }
282
+ if (typeof message !== 'string') {
283
+ throw new Error('AnnouncementManager.announceOnce: message must be a string');
284
+ }
285
+ if (channel !== 'telegram' && channel !== 'dashboard' && channel !== 'log') {
286
+ throw new Error(`AnnouncementManager.announceOnce: invalid channel "${channel}"`);
287
+ }
288
+ if (!fs.existsSync(this.stateDir)) {
289
+ fs.mkdirSync(this.stateDir, { recursive: true });
290
+ }
291
+ const ledger = this.readLedger();
292
+ if (ledger[announcementId]) {
293
+ return false;
294
+ }
295
+ // Record BEFORE emitting so a sink that throws cannot leave us
296
+ // emitting twice on the next call. Worst case: announcement was
297
+ // recorded but the sink failed — operator sees a missed notice
298
+ // once, never a duplicate.
299
+ ledger[announcementId] = {
300
+ channel,
301
+ shownAt: new Date().toISOString(),
302
+ };
303
+ this.writeLedger(ledger);
304
+ try {
305
+ await this.sink(announcementId, message, channel);
306
+ }
307
+ catch {
308
+ // Swallow — see comment above. The ledger entry stands.
309
+ }
310
+ return true;
311
+ }
312
+ /** Has this announcement been shown? Read-only check. */
313
+ hasBeenShown(announcementId) {
314
+ const ledger = this.readLedger();
315
+ return Boolean(ledger[announcementId]);
316
+ }
317
+ readLedger() {
318
+ try {
319
+ if (!fs.existsSync(this.ledgerPath))
320
+ return {};
321
+ const raw = fs.readFileSync(this.ledgerPath, 'utf-8');
322
+ const parsed = JSON.parse(raw);
323
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
324
+ return parsed;
325
+ }
326
+ return {};
327
+ }
328
+ catch {
329
+ return {};
330
+ }
331
+ }
332
+ writeLedger(ledger) {
333
+ const tmpPath = `${this.ledgerPath}.tmp-${process.pid}-${Date.now()}`;
334
+ const serialized = JSON.stringify(ledger, null, 2) + '\n';
335
+ const fd = fs.openSync(tmpPath, 'w', 0o600);
336
+ try {
337
+ fs.writeSync(fd, serialized);
338
+ fs.fsyncSync(fd);
339
+ }
340
+ finally {
341
+ fs.closeSync(fd);
342
+ }
343
+ fs.renameSync(tmpPath, this.ledgerPath);
344
+ }
345
+ }
346
+ function defaultSink(announcementId, message, channel) {
347
+ // Default sink writes to stderr so it never interferes with stdout
348
+ // RPC responses or CLI output capture.
349
+ const line = `[announcement:${channel}] ${announcementId}: ${message}`;
350
+ process.stderr.write(line + '\n');
351
+ }
352
+ //# sourceMappingURL=MigratorStepEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MigratorStepEngine.js","sourceRoot":"","sources":["../../src/core/MigratorStepEngine.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@
18
18
  * - CLAUDE.md sections are appended only if missing (check by heading)
19
19
  * - Scripts are installed only if missing (never overwrite user modifications)
20
20
  */
21
+ import { type MigratorStep, type RunPendingStepsResult } from './MigratorStepEngine.js';
21
22
  export interface MigrationResult {
22
23
  /** What was upgraded */
23
24
  upgraded: string[];
@@ -35,7 +36,37 @@ export interface MigratorConfig {
35
36
  }
36
37
  export declare class PostUpdateMigrator {
37
38
  private config;
39
+ /**
40
+ * F-7 atomic-step engine. Lazily constructed on first access via
41
+ * `getStepEngine()` so existing callers that never touch atomic steps
42
+ * pay zero cost. See `src/core/MigratorStepEngine.ts` for the primitive
43
+ * docs; see `docs/specs/SELF-HEALING-REMEDIATOR-V2-SPEC.md` §A35/§A50
44
+ * for the spec.
45
+ */
46
+ private stepEngine;
38
47
  constructor(config: MigratorConfig);
48
+ /**
49
+ * F-7 atomic-step primitive: register a step that will run once on
50
+ * the release boundary where `step.version <= toVersion`. Idempotent
51
+ * across runs — the engine records every step's outcome in
52
+ * `<stateDir>/migrator-steps-completed.json` keyed by
53
+ * `<version>:<step-name>`.
54
+ *
55
+ * Steps are atomic and self-contained: a failure in one step does not
56
+ * roll back prior steps and does not block subsequent steps.
57
+ *
58
+ * See `docs/specs/SELF-HEALING-REMEDIATOR-V2-SPEC.md` §A35 + §A50.
59
+ */
60
+ registerStep(step: MigratorStep): void;
61
+ /**
62
+ * F-7 atomic-step primitive: execute every pending step. Pending =
63
+ * step.version <= toVersion AND no ledger entry recorded yet.
64
+ *
65
+ * Steps run in registration order. Failures are recorded (never
66
+ * thrown) and do not stop subsequent steps.
67
+ */
68
+ runPendingSteps(fromVersion: string, toVersion: string): Promise<RunPendingStepsResult>;
69
+ private getStepEngine;
39
70
  /**
40
71
  * Run all post-update migrations. Safe to call multiple times —
41
72
  * each migration is idempotent.
@@ -67,6 +98,51 @@ export declare class PostUpdateMigrator {
67
98
  * Non-destructive — only writes SKILL.md files that don't already exist.
68
99
  */
69
100
  private migrateBuiltinSkills;
101
+ /**
102
+ * Phase 2 — install/refresh built-in agentmd jobs. Copies the shipped
103
+ * markdown templates into `.instar/jobs/instar/` and writes their
104
+ * per-slug manifests. Honors operator-disabled state (preserves
105
+ * `enabled: false` + `disabledAtBodyHash` across updates). Retires
106
+ * jobs that are no longer shipped.
107
+ *
108
+ * The `.instar/jobs/user/` namespace is structurally untouched (Seamless
109
+ * Migration Guarantee invariant 4).
110
+ */
111
+ private migrateBuiltinJobs;
112
+ /**
113
+ * Phase 5 — auto-run `instar jobs migrate` for pre-spec agents on update.
114
+ *
115
+ * Behavior:
116
+ * - SKIP entirely if `.instar/jobs/.migration-complete.json` exists
117
+ * (operator already confirmed completion via Dashboard).
118
+ * - SKIP entirely if `.instar/jobs/.migration-abandoned.json` exists
119
+ * (operator explicitly chose to roll back).
120
+ * - SKIP if `.instar/jobs.json` is absent (nothing to migrate).
121
+ * - Otherwise, invoke `jobsMigrate({ defaultAction: 'fork' })` —
122
+ * fork policy preserves the operator's customized body in user/
123
+ * namespace, never silently drops content. This is the
124
+ * spec-mandated default for the auto-run path.
125
+ * - Emit a Dashboard banner event via the migration result so the
126
+ * operator sees "migration ran on update — confirm in Dashboard."
127
+ *
128
+ * Seamless Migration Guarantee invariants enforced at this layer
129
+ * (PR #180 §Seamless Migration Guarantee):
130
+ * #6 in-flight protection — JobScheduler.activeRuns() check is
131
+ * currently a defensive no-op until Phase 4 wires the scheduler
132
+ * back-reference; the migration runs at update time, before the
133
+ * new scheduler instance comes up, so by construction nothing is
134
+ * in flight.
135
+ * #7 transactional safety on interrupt — `jobsMigrate` is structurally
136
+ * safe (backup-first, idempotent, rollback via --abandon).
137
+ * #8 telemetry — outcome is appended to result.upgraded/errors.
138
+ */
139
+ private autoMigrateLegacyJobsJson;
140
+ /** Read the installed package's version, for the migration event's
141
+ * `instarVersion` field. Best-effort — returns undefined on failure. */
142
+ private readBundledInstarVersion;
143
+ /** Best-effort telemetry write. Missing telemetry is degradation, not a
144
+ * release-blocker, so failures are swallowed. */
145
+ private appendMigrationTelemetry;
70
146
  /**
71
147
  * Re-install hooks with the latest templates.
72
148
  * Built-in hooks in instar/ are always overwritten.
@@ -1 +1 @@
1
- {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}