@aopslabs/aops 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/LICENSE +19 -0
  2. package/NOTICE +7 -0
  3. package/README.md +203 -0
  4. package/assets/agent-assets/core/SKILL.md +49 -0
  5. package/assets/agent-assets/core/references/agentspace/SKILL.md +78 -0
  6. package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +108 -0
  7. package/assets/agent-assets/core/references/chatv3/SKILL.md +48 -0
  8. package/assets/agent-assets/core/references/collaborative-work/SKILL.md +85 -0
  9. package/assets/agent-assets/core/references/discuss/SKILL.md +66 -0
  10. package/assets/agent-assets/core/references/docman/SKILL.md +69 -0
  11. package/assets/agent-assets/core/references/hosted-chat/SKILL.md +64 -0
  12. package/assets/agent-assets/core/references/mission/SKILL.md +54 -0
  13. package/assets/agent-assets/core/references/projectman/SKILL.md +86 -0
  14. package/assets/agent-assets/core/references/sys/SKILL.md +36 -0
  15. package/assets/agent-assets/core/references/view/SKILL.md +58 -0
  16. package/assets/agent-assets/core/references/working-disciplines/SKILL.md +69 -0
  17. package/assets/agent-assets/core/user-guides/agent-assets.md +81 -0
  18. package/assets/agent-assets/core/user-guides/agentspace.md +1098 -0
  19. package/assets/agent-assets/core/user-guides/aops-cli.md +1107 -0
  20. package/assets/agent-assets/core/user-guides/aops-system.md +63 -0
  21. package/assets/agent-assets/core/user-guides/chatv3.md +113 -0
  22. package/assets/agent-assets/core/user-guides/docman.md +162 -0
  23. package/assets/agent-assets/core/user-guides/projectman.md +212 -0
  24. package/assets/agent-assets/core/user-guides/sys.md +94 -0
  25. package/assets/agent-assets/core/user-guides/working-disciplines.md +588 -0
  26. package/assets/agent-assets/gateway/aops/SKILL.md +14 -0
  27. package/assets/r6-remote-session-baseline.json +19 -0
  28. package/assets/skills/aops-install/SKILL.md +231 -0
  29. package/assets/skills/aops-install/agents/openai.yaml +4 -0
  30. package/dist/commands/activity.js +352 -0
  31. package/dist/commands/agent-profile.js +653 -0
  32. package/dist/commands/agent.js +710 -0
  33. package/dist/commands/agents-md.js +125 -0
  34. package/dist/commands/api.js +84 -0
  35. package/dist/commands/archive.js +873 -0
  36. package/dist/commands/artifact.js +535 -0
  37. package/dist/commands/assets.js +1414 -0
  38. package/dist/commands/auth/device-login.js +1 -0
  39. package/dist/commands/auth/legacy-export.js +177 -0
  40. package/dist/commands/auth/login.js +426 -0
  41. package/dist/commands/chat.js +1363 -0
  42. package/dist/commands/chatv3.js +1684 -0
  43. package/dist/commands/checkpoint.js +549 -0
  44. package/dist/commands/commercial-artifact.js +475 -0
  45. package/dist/commands/commercial-license.js +594 -0
  46. package/dist/commands/community-auth.js +62 -0
  47. package/dist/commands/community-cockpit.js +185 -0
  48. package/dist/commands/community-console.js +109 -0
  49. package/dist/commands/community-doctor.js +335 -0
  50. package/dist/commands/community-server.js +2062 -0
  51. package/dist/commands/community-setup.js +284 -0
  52. package/dist/commands/discuss.js +1448 -0
  53. package/dist/commands/doc.js +5219 -0
  54. package/dist/commands/experience.js +922 -0
  55. package/dist/commands/host.js +1127 -0
  56. package/dist/commands/init.js +118 -0
  57. package/dist/commands/memory.js +3129 -0
  58. package/dist/commands/mission.js +562 -0
  59. package/dist/commands/official-catalog.js +134 -0
  60. package/dist/commands/plan.js +84 -0
  61. package/dist/commands/playbook.js +415 -0
  62. package/dist/commands/pm/context.js +6 -0
  63. package/dist/commands/pm/index.js +701 -0
  64. package/dist/commands/pm/projectman.js +6266 -0
  65. package/dist/commands/project.js +1080 -0
  66. package/dist/commands/prompt.js +1024 -0
  67. package/dist/commands/repo-sync.js +1907 -0
  68. package/dist/commands/resource.js +527 -0
  69. package/dist/commands/skill.js +1211 -0
  70. package/dist/commands/start-disciplines.js +510 -0
  71. package/dist/commands/start.js +1343 -0
  72. package/dist/commands/target.js +309 -0
  73. package/dist/commands/version.js +42 -0
  74. package/dist/commands/view.js +1852 -0
  75. package/dist/launchers/cockpit.js +28 -0
  76. package/dist/launchers/options.js +74 -0
  77. package/dist/launchers/server.js +41 -0
  78. package/dist/lib/agent-assets/envelope.js +83 -0
  79. package/dist/lib/agent-assets/gateway.js +15 -0
  80. package/dist/lib/agent-assets/guards.js +23 -0
  81. package/dist/lib/agent-assets/hosted-discovery.js +148 -0
  82. package/dist/lib/agent-assets/hosted-package-input.js +154 -0
  83. package/dist/lib/agent-assets/legacy-pointer-migration.js +677 -0
  84. package/dist/lib/agent-assets/native-fs.js +589 -0
  85. package/dist/lib/agent-assets/package-manifest.js +324 -0
  86. package/dist/lib/agent-assets/portable-path.js +67 -0
  87. package/dist/lib/agent-assets/release-input.js +177 -0
  88. package/dist/lib/agent-assets/roots.js +45 -0
  89. package/dist/lib/agent-assets/runtime-binding-reader.js +545 -0
  90. package/dist/lib/agent-assets/runtime-targets.js +50 -0
  91. package/dist/lib/agent-assets/store-reader.js +1212 -0
  92. package/dist/lib/agent-assets/store-types.js +1 -0
  93. package/dist/lib/agent-assets/store-writer.js +1484 -0
  94. package/dist/lib/agent-assets/types.js +1 -0
  95. package/dist/lib/agent-assets/unicode-case-folding-v15-1.generated.js +1548 -0
  96. package/dist/lib/commercial-final-readiness.js +504 -0
  97. package/dist/lib/commercial-lifecycle-smoke-isolation.js +236 -0
  98. package/dist/lib/commercial-managed-postgres-docker-adapter.js +274 -0
  99. package/dist/lib/commercial-setup-readiness-adapter.js +179 -0
  100. package/dist/lib/community-client-contract.js +164 -0
  101. package/dist/lib/community-cockpit-lifecycle.js +601 -0
  102. package/dist/lib/community-command-abort.js +59 -0
  103. package/dist/lib/community-diagnostic.js +237 -0
  104. package/dist/lib/community-docker-adapter.js +498 -0
  105. package/dist/lib/community-home.js +31 -0
  106. package/dist/lib/community-instance-contract.js +148 -0
  107. package/dist/lib/community-instance-layout.js +97 -0
  108. package/dist/lib/community-lifecycle.js +1631 -0
  109. package/dist/lib/community-migration-snapshot.js +770 -0
  110. package/dist/lib/community-native-application-recovery.js +425 -0
  111. package/dist/lib/community-native-child.js +240 -0
  112. package/dist/lib/community-native-database-recovery.js +456 -0
  113. package/dist/lib/community-native-lifecycle.js +2458 -0
  114. package/dist/lib/community-native-migration.js +339 -0
  115. package/dist/lib/community-native-postgres.js +596 -0
  116. package/dist/lib/community-operation-journal.js +773 -0
  117. package/dist/lib/community-operation-lock.js +596 -0
  118. package/dist/lib/community-release-resolver.js +291 -0
  119. package/dist/lib/community-release-verifier.js +475 -0
  120. package/dist/lib/community-repo-discovery.js +252 -0
  121. package/dist/lib/community-setup-server-env.js +203 -0
  122. package/dist/lib/external-url.js +110 -0
  123. package/dist/lib/official-catalog-gateway.js +108 -0
  124. package/dist/lib/official-catalog.js +364 -0
  125. package/dist/lib/server-bootstrap.js +240 -0
  126. package/dist/lib/setup-agent-assets-bridge.js +176 -0
  127. package/dist/lib/setup-agent-assets-release.js +52 -0
  128. package/dist/lib/setup-external-postgres.js +108 -0
  129. package/dist/lib/setup-init-orchestrator.js +990 -0
  130. package/dist/lib/setup-install-guide.js +52 -0
  131. package/dist/lib/setup-installer-release.js +47 -0
  132. package/dist/lib/setup-local-postgres.js +329 -0
  133. package/dist/lib/setup-official-catalog-bridge.js +148 -0
  134. package/dist/lib/setup-readiness.js +888 -0
  135. package/dist/lib/tui-launcher.js +59 -0
  136. package/dist/main.js +150 -0
  137. package/dist/seeds/agents-md.js +54 -0
  138. package/dist/utils/agent-gateway.js +275 -0
  139. package/dist/utils/agents-md.js +281 -0
  140. package/dist/utils/api.js +255 -0
  141. package/dist/utils/chatv3-session-store.js +185 -0
  142. package/dist/utils/command.js +67 -0
  143. package/dist/utils/community-host-runtime.js +376 -0
  144. package/dist/utils/config.js +1015 -0
  145. package/dist/utils/discussion-workspace.js +552 -0
  146. package/dist/utils/experience-workspace.js +326 -0
  147. package/dist/utils/guide-paths.js +67 -0
  148. package/dist/utils/hosted-sugar.js +56 -0
  149. package/dist/utils/hosted-workspace.js +229 -0
  150. package/dist/utils/memory-workspace.js +537 -0
  151. package/dist/utils/operator-runtime.js +199 -0
  152. package/dist/utils/password-crypto.js +39 -0
  153. package/dist/utils/playbook-workspace.js +479 -0
  154. package/dist/utils/project-context.js +255 -0
  155. package/dist/utils/prompts.js +70 -0
  156. package/dist/utils/refresh-race.js +28 -0
  157. package/dist/utils/repo-config.js +109 -0
  158. package/dist/utils/repo-first-projectman.js +194 -0
  159. package/dist/utils/repo-first-storage.js +13 -0
  160. package/dist/utils/repo-first-view.js +305 -0
  161. package/dist/utils/session-guidance.js +278 -0
  162. package/dist/utils/session-state.js +137 -0
  163. package/dist/utils/table.js +39 -0
  164. package/dist/utils/transient-fs.js +49 -0
  165. package/dist/utils/workspace-root.js +1 -0
  166. package/launchers/aops-cockpit.ps1 +15 -0
  167. package/launchers/aops-cockpit.sh +16 -0
  168. package/launchers/aops-server.ps1 +15 -0
  169. package/launchers/aops-server.sh +16 -0
  170. package/native/tui/win32-x64/aops-tui.exe +0 -0
  171. package/package.json +81 -0
@@ -0,0 +1,339 @@
1
+ import { applyCommunityStrictPgSchema, planCommunityStrictPgSchema, } from '@aopslabs/aops-pg-bootstrap';
2
+ import { lstatSync, readFileSync, realpathSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { asCommunityDiagnosticError, } from './community-diagnostic.js';
5
+ export const COMMUNITY_NATIVE_MIGRATION_POLICY_PATH = 'apps/aops-server/scripts/community-migration-policy-v1.json';
6
+ export const COMMUNITY_NATIVE_PACKAGE_MIGRATION_POLICY_PATH = 'scripts/community-migration-policy-package-v1.json';
7
+ const MAX_POLICY_BYTES = 2 * 1024 * 1024;
8
+ const INSTANCE_NAME = /^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$/;
9
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
10
+ const PREFIXED_SHA256 = /^sha256:[a-f0-9]{64}$/;
11
+ const RAW_SHA256 = /^[a-f0-9]{64}$/;
12
+ function isRecord(value) {
13
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
14
+ }
15
+ function exactKeys(value, expected) {
16
+ const actual = Object.keys(value).sort();
17
+ const wanted = [...expected].sort();
18
+ return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
19
+ }
20
+ function isWithin(root, candidate) {
21
+ const relative = path.relative(path.resolve(root), path.resolve(candidate));
22
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
23
+ }
24
+ function throwIfAborted(signal) {
25
+ if (signal?.aborted)
26
+ throw new Error('community_operation_aborted');
27
+ }
28
+ export function readCommunityNativeMigrationPolicy(sourceRoot) {
29
+ const resolvedRoot = path.resolve(sourceRoot);
30
+ const rootStats = lstatSync(resolvedRoot);
31
+ if (!rootStats.isDirectory() || rootStats.isSymbolicLink()) {
32
+ throw new Error('community_native_migration_source_root_invalid');
33
+ }
34
+ const canonicalRoot = realpathSync.native(resolvedRoot);
35
+ if (path.relative(resolvedRoot, canonicalRoot) !== '' || path.relative(canonicalRoot, resolvedRoot) !== '') {
36
+ throw new Error('community_native_migration_source_root_alias_refused');
37
+ }
38
+ const manifest = (() => {
39
+ try {
40
+ return JSON.parse(readFileSync(path.join(canonicalRoot, 'package.json'), 'utf8'));
41
+ }
42
+ catch {
43
+ return {};
44
+ }
45
+ })();
46
+ const relativePolicyPath = manifest.name === '@aopslabs/aops-server'
47
+ ? COMMUNITY_NATIVE_PACKAGE_MIGRATION_POLICY_PATH
48
+ : COMMUNITY_NATIVE_MIGRATION_POLICY_PATH;
49
+ const policyPath = path.resolve(canonicalRoot, ...relativePolicyPath.split('/'));
50
+ if (!isWithin(canonicalRoot, policyPath))
51
+ throw new Error('community_native_migration_policy_path_escape');
52
+ const stats = lstatSync(policyPath);
53
+ if (!stats.isFile() || stats.isSymbolicLink() || stats.size < 1 || stats.size > MAX_POLICY_BYTES) {
54
+ throw new Error('community_native_migration_policy_file_invalid');
55
+ }
56
+ const canonicalPolicyPath = realpathSync.native(policyPath);
57
+ if (!isWithin(canonicalRoot, canonicalPolicyPath) || path.relative(policyPath, canonicalPolicyPath) !== '') {
58
+ throw new Error('community_native_migration_policy_path_unsafe');
59
+ }
60
+ try {
61
+ return JSON.parse(readFileSync(canonicalPolicyPath, 'utf8'));
62
+ }
63
+ catch {
64
+ throw new Error('community_native_migration_policy_json_invalid');
65
+ }
66
+ }
67
+ export async function planCommunityNativeMigration(params, dependencies = {}) {
68
+ if (!path.isAbsolute(params.sourceRoot) || !params.repoUrl) {
69
+ throw new Error('community_native_migration_planning_invocation_invalid');
70
+ }
71
+ throwIfAborted(params.signal);
72
+ let policy;
73
+ try {
74
+ policy = readCommunityNativeMigrationPolicy(params.sourceRoot);
75
+ }
76
+ catch (error) {
77
+ throw asCommunityDiagnosticError(error, {
78
+ code: 'community_native_migration_configuration_failed',
79
+ phase: 'configuration',
80
+ });
81
+ }
82
+ let planning;
83
+ try {
84
+ planning = await (dependencies.planStrictPgSchema ?? planCommunityStrictPgSchema)({
85
+ repoUrl: params.repoUrl,
86
+ workspaceRoot: params.sourceRoot,
87
+ policy,
88
+ });
89
+ }
90
+ catch (error) {
91
+ throw asCommunityDiagnosticError(error, {
92
+ code: 'community_native_migration_planning_failed',
93
+ phase: 'inspect-schema',
94
+ });
95
+ }
96
+ throwIfAborted(params.signal);
97
+ return { planning, policy };
98
+ }
99
+ export function assertCommunityNativeMigrationReceiptV1(value) {
100
+ if (!isRecord(value) || !exactKeys(value, [
101
+ 'schemaVersion', 'status', 'instanceName', 'installId', 'sourceFingerprint', 'completedAt',
102
+ 'policyId', 'targetLineageId', 'resultLineageId', 'action', 'pendingMigrationCount',
103
+ 'policySha256', 'bundleSha256', 'acceptedPlanSha256', 'sourceMigrationStateFingerprintSha256',
104
+ 'resultSchemaFingerprintSha256', 'resultReceiptFingerprintSha256',
105
+ 'resultMigrationStateFingerprintSha256', 'durableAcceptanceAction', 'durableAcceptanceAt',
106
+ 'snapshotEvidenceKind', 'snapshotEvidenceSha256', 'latestAppliedPlanSha256',
107
+ 'latestAppliedSourceMigrationStateFingerprintSha256',
108
+ 'latestAppliedResultStateFingerprintSha256',
109
+ 'latestAppliedEvidenceKind', 'latestAppliedEvidenceSha256', 'latestAppliedAt',
110
+ 'recoveredAppliedPlanSha256', 'migrationLogCount',
111
+ ])) {
112
+ throw new Error('community_native_migration_receipt_schema_invalid');
113
+ }
114
+ if (value.schemaVersion !== 1 || value.status !== 'community-native-migration-verified' ||
115
+ !INSTANCE_NAME.test(String(value.instanceName)) || !UUID.test(String(value.installId)) ||
116
+ !PREFIXED_SHA256.test(String(value.sourceFingerprint)) ||
117
+ Number.isNaN(Date.parse(String(value.completedAt))) ||
118
+ typeof value.policyId !== 'string' || value.policyId.length < 1 ||
119
+ typeof value.targetLineageId !== 'string' || value.targetLineageId.length < 1 ||
120
+ typeof value.resultLineageId !== 'string' || value.resultLineageId.length < 1 ||
121
+ (value.action !== 'migrate' && value.action !== 'verify-only') ||
122
+ (value.durableAcceptanceAction !== 'migrate' && value.durableAcceptanceAction !== 'verify-only') ||
123
+ Number.isNaN(Date.parse(String(value.durableAcceptanceAt))) ||
124
+ !['managed-verified-backup', 'external-snapshot-attestation', null]
125
+ .includes(value.snapshotEvidenceKind) ||
126
+ !['managed-verified-backup', 'external-snapshot-attestation', null]
127
+ .includes(value.latestAppliedEvidenceKind) ||
128
+ (value.latestAppliedAt !== null && Number.isNaN(Date.parse(String(value.latestAppliedAt)))) ||
129
+ !Number.isSafeInteger(value.pendingMigrationCount) || Number(value.pendingMigrationCount) < 0 ||
130
+ !Number.isSafeInteger(value.migrationLogCount) || Number(value.migrationLogCount) < 0 ||
131
+ ![
132
+ value.policySha256,
133
+ value.bundleSha256,
134
+ value.acceptedPlanSha256,
135
+ value.sourceMigrationStateFingerprintSha256,
136
+ value.resultSchemaFingerprintSha256,
137
+ value.resultReceiptFingerprintSha256,
138
+ value.resultMigrationStateFingerprintSha256,
139
+ ].every((digest) => RAW_SHA256.test(String(digest)))
140
+ || ![value.snapshotEvidenceSha256, value.latestAppliedPlanSha256,
141
+ value.latestAppliedSourceMigrationStateFingerprintSha256,
142
+ value.latestAppliedResultStateFingerprintSha256,
143
+ value.latestAppliedEvidenceSha256, value.recoveredAppliedPlanSha256]
144
+ .every((digest) => digest === null || RAW_SHA256.test(String(digest)))
145
+ || (value.snapshotEvidenceKind === null) !== (value.snapshotEvidenceSha256 === null)
146
+ || (value.latestAppliedEvidenceKind === null) !== (value.latestAppliedEvidenceSha256 === null)
147
+ || (value.latestAppliedPlanSha256 === null) !== (value.latestAppliedAt === null)
148
+ || (value.latestAppliedPlanSha256 === null) !==
149
+ (value.latestAppliedSourceMigrationStateFingerprintSha256 === null)
150
+ || (value.latestAppliedPlanSha256 === null) !==
151
+ (value.latestAppliedResultStateFingerprintSha256 === null)
152
+ || value.action !== value.durableAcceptanceAction
153
+ || (value.action === 'migrate' && value.latestAppliedPlanSha256 !== null &&
154
+ value.latestAppliedPlanSha256 !== value.acceptedPlanSha256)
155
+ || (value.action === 'migrate' && value.latestAppliedPlanSha256 !== null && (value.latestAppliedSourceMigrationStateFingerprintSha256 !==
156
+ value.sourceMigrationStateFingerprintSha256 ||
157
+ value.latestAppliedResultStateFingerprintSha256 !==
158
+ value.resultMigrationStateFingerprintSha256 ||
159
+ value.latestAppliedEvidenceKind !== value.snapshotEvidenceKind ||
160
+ value.latestAppliedEvidenceSha256 !== value.snapshotEvidenceSha256 ||
161
+ value.latestAppliedAt !== value.durableAcceptanceAt))
162
+ || (value.recoveredAppliedPlanSha256 !== null &&
163
+ value.recoveredAppliedPlanSha256 !== value.latestAppliedPlanSha256)) {
164
+ throw new Error('community_native_migration_receipt_schema_invalid');
165
+ }
166
+ return value;
167
+ }
168
+ function receiptFromResult(invocation, result, completedAt, migrationLogCount) {
169
+ let recoveredAppliedPlanSha256 = null;
170
+ const prior = invocation.priorIntentExpectation;
171
+ if (prior) {
172
+ const latest = result.latestAppliedAcceptance;
173
+ if (!latest || latest.acceptedPlanSha256 !== prior.acceptedPlanSha256 ||
174
+ latest.sourceFingerprintSha256 !== prior.sourceMigrationStateFingerprintSha256 ||
175
+ latest.evidenceKind !== prior.snapshotEvidenceKind ||
176
+ latest.evidenceSha256 !== prior.snapshotEvidenceSha256) {
177
+ throw new Error('community_native_migration_intent_not_reconciled');
178
+ }
179
+ recoveredAppliedPlanSha256 = prior.acceptedPlanSha256;
180
+ }
181
+ const latestAppliedAt = result.latestAppliedAcceptance?.acceptedAt ?? null;
182
+ return assertCommunityNativeMigrationReceiptV1({
183
+ schemaVersion: 1,
184
+ status: 'community-native-migration-verified',
185
+ instanceName: invocation.instanceName,
186
+ installId: invocation.installId,
187
+ sourceFingerprint: invocation.sourceFingerprint,
188
+ completedAt,
189
+ policyId: result.policyId,
190
+ targetLineageId: result.migrationPlan.target.lineageId,
191
+ resultLineageId: result.lineageId,
192
+ action: result.migrationPlan.action,
193
+ pendingMigrationCount: result.migrationPlan.pendingMigrations.length,
194
+ policySha256: result.migrationPlan.policySha256,
195
+ bundleSha256: result.migrationPlan.bundleSha256,
196
+ acceptedPlanSha256: result.acceptedPlanSha256,
197
+ sourceMigrationStateFingerprintSha256: result.sourceFingerprintSha256,
198
+ resultSchemaFingerprintSha256: result.schemaFingerprintSha256,
199
+ resultReceiptFingerprintSha256: result.receiptFingerprintSha256,
200
+ resultMigrationStateFingerprintSha256: result.stateFingerprintSha256,
201
+ durableAcceptanceAction: result.durableAcceptance.action,
202
+ durableAcceptanceAt: latestAppliedAt ?? result.durableAcceptance.acceptedAt,
203
+ snapshotEvidenceKind: result.durableAcceptance.evidenceKind,
204
+ snapshotEvidenceSha256: result.durableAcceptance.evidenceSha256,
205
+ latestAppliedPlanSha256: result.latestAppliedPlanSha256,
206
+ latestAppliedSourceMigrationStateFingerprintSha256: result.latestAppliedAcceptance?.sourceFingerprintSha256 ?? null,
207
+ latestAppliedResultStateFingerprintSha256: result.latestAppliedAcceptance?.resultStateFingerprintSha256 ?? null,
208
+ latestAppliedEvidenceKind: result.latestAppliedAcceptance?.evidenceKind ?? null,
209
+ latestAppliedEvidenceSha256: result.latestAppliedAcceptance?.evidenceSha256 ?? null,
210
+ latestAppliedAt,
211
+ recoveredAppliedPlanSha256,
212
+ migrationLogCount,
213
+ });
214
+ }
215
+ export async function runCommunityNativeMigration(invocation, dependencies = {}) {
216
+ const prior = invocation.priorIntentExpectation;
217
+ if (!path.isAbsolute(invocation.sourceRoot) || !invocation.repoUrl ||
218
+ !INSTANCE_NAME.test(invocation.instanceName) || !UUID.test(invocation.installId) ||
219
+ !PREFIXED_SHA256.test(invocation.sourceFingerprint) ||
220
+ (prior !== undefined && prior !== null && (!RAW_SHA256.test(prior.acceptedPlanSha256) ||
221
+ !RAW_SHA256.test(prior.sourceMigrationStateFingerprintSha256) ||
222
+ !['managed-verified-backup', 'external-snapshot-attestation', null]
223
+ .includes(prior.snapshotEvidenceKind) ||
224
+ (prior.snapshotEvidenceSha256 !== null && !RAW_SHA256.test(prior.snapshotEvidenceSha256)) ||
225
+ (prior.snapshotEvidenceKind === null) !== (prior.snapshotEvidenceSha256 === null))) ||
226
+ (invocation.requiredPlanSha256 !== undefined && !RAW_SHA256.test(invocation.requiredPlanSha256)) ||
227
+ (invocation.requiredAction !== undefined && invocation.requiredAction !== 'verify-only')) {
228
+ throw new Error('community_native_migration_invocation_invalid');
229
+ }
230
+ throwIfAborted(invocation.signal);
231
+ let policy;
232
+ try {
233
+ policy = readCommunityNativeMigrationPolicy(invocation.sourceRoot);
234
+ }
235
+ catch (error) {
236
+ throw asCommunityDiagnosticError(error, {
237
+ code: 'community_native_migration_configuration_failed',
238
+ phase: 'configuration',
239
+ });
240
+ }
241
+ const logs = [];
242
+ let planning;
243
+ let evidence = null;
244
+ if (invocation.snapshotEvidenceProvider || invocation.requiredPlanSha256 || invocation.requiredAction) {
245
+ try {
246
+ planning = await (dependencies.planStrictPgSchema ?? planCommunityStrictPgSchema)({
247
+ repoUrl: invocation.repoUrl,
248
+ workspaceRoot: invocation.sourceRoot,
249
+ policy,
250
+ });
251
+ }
252
+ catch (error) {
253
+ throw asCommunityDiagnosticError(error, {
254
+ code: 'community_native_migration_planning_failed',
255
+ phase: 'inspect-schema',
256
+ });
257
+ }
258
+ throwIfAborted(invocation.signal);
259
+ if (invocation.requiredPlanSha256 !== undefined &&
260
+ planning.acceptedPlanSha256 !== invocation.requiredPlanSha256) {
261
+ throw new Error(`community_native_required_migration_plan_mismatch:expected=${invocation.requiredPlanSha256}:actual=${planning.acceptedPlanSha256}`);
262
+ }
263
+ if (invocation.requiredAction !== undefined && planning.migrationPlan.action !== invocation.requiredAction) {
264
+ throw new Error(`community_native_required_migration_action_mismatch:${planning.migrationPlan.action}`);
265
+ }
266
+ if (invocation.snapshotEvidenceProvider) {
267
+ try {
268
+ evidence = await invocation.snapshotEvidenceProvider({
269
+ planning,
270
+ policy,
271
+ sourceRoot: invocation.sourceRoot,
272
+ repoUrl: invocation.repoUrl,
273
+ signal: invocation.signal,
274
+ });
275
+ }
276
+ catch (error) {
277
+ throw asCommunityDiagnosticError(error, {
278
+ code: 'community_native_migration_snapshot_failed',
279
+ phase: 'snapshot',
280
+ details: {
281
+ migrationAction: planning.migrationPlan.action,
282
+ pendingMigrationCount: planning.migrationPlan.pendingMigrations.length,
283
+ },
284
+ });
285
+ }
286
+ throwIfAborted(invocation.signal);
287
+ if (planning.requiresSnapshotEvidence && evidence === null) {
288
+ throw new Error('community_native_snapshot_evidence_required');
289
+ }
290
+ if (evidence && !path.isAbsolute(evidence.path)) {
291
+ throw new Error('community_native_snapshot_evidence_path_invalid');
292
+ }
293
+ }
294
+ }
295
+ let result;
296
+ let migrationPhase = 'inspect-schema';
297
+ try {
298
+ result = await (dependencies.applyStrictPgSchema ?? applyCommunityStrictPgSchema)({
299
+ repoUrl: invocation.repoUrl,
300
+ workspaceRoot: invocation.sourceRoot,
301
+ policy,
302
+ expectedPlanSha256: planning?.acceptedPlanSha256,
303
+ snapshotEvidencePath: evidence?.path,
304
+ snapshotPolicy: evidence?.policy,
305
+ onPlanAccepted: async (context) => {
306
+ migrationPhase = context.migrationPlan.action === 'migrate' ? 'apply' : 'verify';
307
+ await invocation.onPlanAccepted?.(context);
308
+ },
309
+ logs,
310
+ });
311
+ }
312
+ catch (error) {
313
+ if (invocation.signal?.aborted)
314
+ throw new Error('community_operation_aborted');
315
+ throw asCommunityDiagnosticError(error, {
316
+ code: 'community_native_migration_failed',
317
+ phase: migrationPhase,
318
+ details: planning ? {
319
+ migrationAction: planning.migrationPlan.action,
320
+ pendingMigrationCount: planning.migrationPlan.pendingMigrations.length,
321
+ } : undefined,
322
+ });
323
+ }
324
+ throwIfAborted(invocation.signal);
325
+ throwIfAborted(invocation.signal);
326
+ try {
327
+ return receiptFromResult(invocation, result, (dependencies.now ?? (() => new Date()))().toISOString(), logs.length);
328
+ }
329
+ catch (error) {
330
+ throw asCommunityDiagnosticError(error, {
331
+ code: 'community_native_migration_result_failed',
332
+ phase: 'verify',
333
+ details: {
334
+ migrationAction: result.migrationPlan.action,
335
+ pendingMigrationCount: result.migrationPlan.pendingMigrations.length,
336
+ },
337
+ });
338
+ }
339
+ }