openyida 2026.7.18 → 2026.7.21

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 (200) hide show
  1. package/README.md +37 -2
  2. package/bin/yida.js +113 -18
  3. package/docs/capabilities.md +202 -0
  4. package/lib/agent-center/agent-center.js +2 -3
  5. package/lib/app/app-list.js +3 -4
  6. package/lib/app/build-page.js +13 -6
  7. package/lib/app/check-page.js +16 -6
  8. package/lib/app/compile.js +17 -7
  9. package/lib/app/create-app.js +14 -2
  10. package/lib/app/create-form/api-path.js +25 -0
  11. package/lib/app/create-form/args.js +13 -0
  12. package/lib/app/create-form/commands.js +4 -0
  13. package/lib/app/create-form/definition-reader.js +23 -23
  14. package/lib/app/create-form/field-normalizers.js +26 -7
  15. package/lib/app/create-form/schema-patch.js +4 -1
  16. package/lib/app/create-form.js +155 -68
  17. package/lib/app/create-page.js +47 -10
  18. package/lib/app/generate-page.js +20 -1
  19. package/lib/app/get-form-config.js +2 -1
  20. package/lib/app/get-schema.js +67 -15
  21. package/lib/app/import-app.js +94 -42
  22. package/lib/app/list-forms.js +4 -8
  23. package/lib/app/page-ir.js +140 -0
  24. package/lib/app/publish.js +289 -556
  25. package/lib/app/schema-field-resolution.js +370 -0
  26. package/lib/app/services/app-reader.js +85 -0
  27. package/lib/app/services/app-service.js +235 -0
  28. package/lib/app/services/canvas-page-compiler.js +91 -0
  29. package/lib/app/services/canvas-page-schema-builder.js +149 -0
  30. package/lib/app/services/field-bindings.js +68 -0
  31. package/lib/app/services/form-compiler.js +1922 -0
  32. package/lib/app/services/form-mode-service.js +182 -0
  33. package/lib/app/services/form-schema-patcher.js +333 -0
  34. package/lib/app/services/form-schema-reader.js +59 -0
  35. package/lib/app/services/form-service.js +379 -0
  36. package/lib/app/services/form-validation.js +562 -0
  37. package/lib/app/services/native-page-compiler.js +92 -0
  38. package/lib/app/services/native-page-schema-builder.js +428 -0
  39. package/lib/app/services/page-resource-service.js +185 -0
  40. package/lib/app/update-app.js +22 -9
  41. package/lib/app/update-form-config.js +4 -2
  42. package/lib/asset/asset-cmd.js +19 -6
  43. package/lib/auth/oauth-loopback.js +376 -15
  44. package/lib/auth/token-auth.js +34 -3
  45. package/lib/auth/token-store.js +22 -4
  46. package/lib/basic-info/basic-info.js +2 -1
  47. package/lib/bridge/bridge.js +43 -18
  48. package/lib/core/agent-capabilities.js +5 -3
  49. package/lib/core/command-errors.js +38 -0
  50. package/lib/core/command-manifest.js +59 -1
  51. package/lib/core/copy.js +12 -0
  52. package/lib/core/doctor.js +15 -4
  53. package/lib/core/env-cmd.js +1 -1
  54. package/lib/core/env.js +7 -6
  55. package/lib/core/i18n.js +66 -8
  56. package/lib/core/legacy-schema-guard.js +408 -0
  57. package/lib/core/locales/en.js +38 -46
  58. package/lib/core/locales/zh.js +30 -46
  59. package/lib/core/sample.js +12 -2
  60. package/lib/core/utils.js +334 -66
  61. package/lib/core/yida-client.js +108 -5
  62. package/lib/corp-efficiency/corp-efficiency.js +2 -2
  63. package/lib/corp-manager/corp-manager.js +3 -3
  64. package/lib/formula/evaluate.js +11 -68
  65. package/lib/formula/field-refs.js +83 -0
  66. package/lib/i18n-management/i18n-management.js +2 -3
  67. package/lib/process/configure-process.js +44 -1992
  68. package/lib/process/create-process.js +54 -87
  69. package/lib/process/preview-process.js +20 -8
  70. package/lib/process/services/process-compiler.js +2056 -0
  71. package/lib/process/services/process-reader.js +232 -0
  72. package/lib/process/services/process-resource-service.js +571 -0
  73. package/lib/process/services/process-service.js +122 -0
  74. package/lib/process/services/process-stage-checkpoint.js +246 -0
  75. package/lib/report/append.js +7 -26
  76. package/lib/report/http.js +31 -5
  77. package/lib/report/index.js +10 -2
  78. package/lib/samples/yida-canvas-custom-page/business-list.canvas.jsx +63 -14
  79. package/lib/samples/yida-canvas-custom-page/dashboard-overview.canvas.jsx +176 -32
  80. package/lib/samples/yida-canvas-custom-page/dashboard-starter.canvas.jsx +5 -2
  81. package/lib/samples/yida-canvas-custom-page/data-management.canvas.jsx +228 -14
  82. package/lib/samples/yida-canvas-custom-page/portal-shell-home.canvas.jsx +2 -2
  83. package/lib/samples/yida-canvas-custom-page/split-pane-detail.canvas.jsx +206 -10
  84. package/lib/samples/yida-custom-page/data-management.oyd.jsx +14 -3
  85. package/lib/samples/yida-custom-page/design-tokens.js +2 -2
  86. package/lib/samples/yida-custom-page/detail-profile.oyd.jsx +1 -1
  87. package/lib/samples/yida-custom-page/portal-shell-home.oyd.jsx +7 -2
  88. package/lib/samples/yida-custom-page/split-pane-detail.oyd.jsx +2 -1
  89. package/lib/schema/adapters/app-adapter.js +210 -0
  90. package/lib/schema/adapters/form-adapter.js +1362 -0
  91. package/lib/schema/adapters/keys.js +19 -0
  92. package/lib/schema/adapters/page-adapter.js +566 -0
  93. package/lib/schema/adapters/process-adapter.js +519 -0
  94. package/lib/schema/applier.js +1878 -0
  95. package/lib/schema/apply-store.js +1083 -0
  96. package/lib/schema/command.js +645 -0
  97. package/lib/schema/dependency-graph.js +83 -0
  98. package/lib/schema/errors.js +481 -0
  99. package/lib/schema/hash.js +9 -0
  100. package/lib/schema/manifest-limits.js +177 -0
  101. package/lib/schema/manifest-loader.js +309 -0
  102. package/lib/schema/manifest-schema-v1.json +193 -0
  103. package/lib/schema/normalize-manifest.js +281 -0
  104. package/lib/schema/page-canvas-foundation.js +447 -0
  105. package/lib/schema/page-data-source-builder.js +561 -0
  106. package/lib/schema/page-foundation.js +556 -0
  107. package/lib/schema/page-source-loader.js +314 -0
  108. package/lib/schema/planner.js +691 -0
  109. package/lib/schema/remote-dispatch-boundary.js +39 -0
  110. package/lib/schema/remote-missing.js +21 -0
  111. package/lib/schema/remote-reader.js +189 -0
  112. package/lib/schema/resource-registry.js +157 -0
  113. package/lib/schema/server-revision.js +71 -0
  114. package/lib/schema/sort.js +28 -0
  115. package/lib/schema/state-store.js +589 -0
  116. package/package.json +10 -8
  117. package/scripts/check-release-risks.js +254 -0
  118. package/scripts/generate-command-docs.js +6 -1
  119. package/scripts/i18n-baseline.json +11 -11
  120. package/scripts/postinstall.js +8 -12
  121. package/scripts/validate-ci.sh +15 -11
  122. package/scripts/validate-i18n.js +30 -9
  123. package/scripts/validate-package-size.js +5 -2
  124. package/scripts/validate-skills.js +4 -0
  125. package/scripts/validate-structure.js +15 -0
  126. package/yida-skills/SKILL.md +117 -30
  127. package/yida-skills/references/schema-as-code-phase1.md +99 -0
  128. package/yida-skills/references/setup-and-env.md +59 -59
  129. package/yida-skills/references/task-retrospective.md +6 -6
  130. package/yida-skills/skills/yida-app/SKILL.md +78 -17
  131. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +18 -7
  132. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +3 -3
  133. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +15 -0
  134. package/yida-skills/skills/yida-create-app/SKILL.md +21 -3
  135. package/yida-skills/skills/yida-create-form-page/SKILL.md +19 -1
  136. package/yida-skills/skills/yida-create-page/SKILL.md +16 -3
  137. package/yida-skills/skills/yida-create-process/SKILL.md +100 -4
  138. package/yida-skills/skills/yida-custom-page/SKILL.md +19 -4
  139. package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
  140. package/yida-skills/skills/yida-dashboard/references/pitfalls.md +1 -1
  141. package/yida-skills/skills/yida-get-schema/SKILL.md +49 -5
  142. package/yida-skills/skills/yida-i18n/SKILL.md +1 -1
  143. package/yida-skills/skills/yida-integration/SKILL.md +7 -1
  144. package/yida-skills/skills/yida-login/SKILL.md +50 -99
  145. package/yida-skills/skills/yida-page-config/SKILL.md +7 -1
  146. package/yida-skills/skills/yida-page-uiux/references/app/blueprint.md +0 -1
  147. package/yida-skills/skills/yida-page-uiux/references/app/navigation-patterns.md +0 -1
  148. package/yida-skills/skills/yida-page-uiux/references/app/role-journey.md +0 -1
  149. package/yida-skills/skills/yida-page-uiux/references/dashboard/app-blueprint.md +0 -1
  150. package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +0 -1
  151. package/yida-skills/skills/yida-page-uiux/references/dashboard/component-contracts.md +0 -1
  152. package/yida-skills/skills/yida-page-uiux/references/dashboard/layout-patterns.md +0 -1
  153. package/yida-skills/skills/yida-page-uiux/references/dashboard/theme-recipes.md +0 -1
  154. package/yida-skills/skills/yida-page-uiux/references/detail/object-narrative.md +0 -1
  155. package/yida-skills/skills/yida-page-uiux/references/detail/section-patterns.md +0 -1
  156. package/yida-skills/skills/yida-page-uiux/references/detail/timeline-and-related.md +0 -1
  157. package/yida-skills/skills/yida-page-uiux/references/landing/assets-workflow.md +0 -1
  158. package/yida-skills/skills/yida-page-uiux/references/landing/industry-playbooks.md +0 -1
  159. package/yida-skills/skills/yida-page-uiux/references/landing/research-levels.md +0 -1
  160. package/yida-skills/skills/yida-page-uiux/references/landing/section-patterns.md +0 -1
  161. package/yida-skills/skills/yida-page-uiux/references/list/drawer-detail.md +0 -1
  162. package/yida-skills/skills/yida-page-uiux/references/list/empty-loading-error.md +0 -1
  163. package/yida-skills/skills/yida-page-uiux/references/list/filter-patterns.md +0 -1
  164. package/yida-skills/skills/yida-page-uiux/references/list/table-patterns.md +0 -1
  165. package/yida-skills/skills/yida-page-uiux/references/scenes/screen.md +0 -1
  166. package/yida-skills/skills/yida-page-uiux/references/workbench/entry-patterns.md +0 -1
  167. package/yida-skills/skills/yida-page-uiux/references/workbench/portal-layouts.md +0 -1
  168. package/yida-skills/skills/yida-page-uiux/references/workbench/task-feed.md +0 -1
  169. package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +1 -1
  170. package/yida-skills/skills/yida-process-rule/SKILL.md +35 -1
  171. package/yida-skills/skills/yida-publish-page/SKILL.md +46 -4
  172. package/yida-skills/skills/yida-report/SKILL.md +9 -235
  173. package/yida-skills/skills/yida-report/references/schema-builder-details.md +239 -0
  174. package/yida-skills/skills/yida-skill-evaluator/SKILL.md +170 -0
  175. package/yida-skills/skills-index.json +238 -54
  176. package/lib/core/locales/ar.js +0 -834
  177. package/lib/core/locales/de.js +0 -834
  178. package/lib/core/locales/es.js +0 -834
  179. package/lib/core/locales/fr.js +0 -834
  180. package/lib/core/locales/hi.js +0 -834
  181. package/lib/core/locales/ja.js +0 -1227
  182. package/lib/core/locales/ko.js +0 -836
  183. package/lib/core/locales/pt.js +0 -834
  184. package/lib/core/locales/vi.js +0 -834
  185. package/lib/core/locales/zh-HK.js +0 -1263
  186. package/project/pages/src/demo-birthday-game.oyd.jsx +0 -832
  187. package/project/pages/src/demo-chip-insight.oyd.jsx +0 -983
  188. package/project/pages/src/demo-compat-smoke.oyd.jsx +0 -58
  189. package/project/pages/src/demo-crm-batch-entry.oyd.jsx +0 -805
  190. package/project/pages/src/demo-crm-dashboard.oyd.jsx +0 -677
  191. package/project/pages/src/demo-future-vision-2026.oyd.jsx +0 -1102
  192. package/project/pages/src/demo-ppt.oyd.jsx +0 -1192
  193. package/project/pages/src/demo-salary-calculator.oyd.jsx +0 -904
  194. package/project/pages/src/openyida-knowledge-doc.oyd.jsx +0 -1714
  195. package/yida-skills/skills/large-file-write/SKILL.md +0 -93
  196. package/yida-skills/skills/large-file-write/references/write-patterns.md +0 -147
  197. package/yida-skills/skills/large-file-write/scripts/write.js +0 -157
  198. package/yida-skills/skills/sls-log-workbench/SKILL.md +0 -134
  199. package/yida-skills/skills/sls-log-workbench/references/workbench-reference.md +0 -130
  200. package/yida-skills/skills/sls-log-workbench/sls-query.js +0 -295
@@ -0,0 +1,645 @@
1
+ 'use strict';
2
+
3
+ const { loadManifest } = require('./manifest-loader');
4
+ const { normalizeManifest } = require('./normalize-manifest');
5
+ const {
6
+ APPLY_KIND,
7
+ isTrustedSchemaError,
8
+ schemaError,
9
+ toApplyFailurePayload,
10
+ toFailurePayload,
11
+ toPlanFailurePayload,
12
+ toSuccessPayload,
13
+ } = require('./errors');
14
+ const { applySchema } = require('./applier');
15
+ const { readObservedResources } = require('./remote-reader');
16
+ const { createDefaultRegistry } = require('./resource-registry');
17
+ const { readState } = require('./state-store');
18
+ const {
19
+ PLAN_KIND,
20
+ createPlan,
21
+ selectObservableResources,
22
+ } = require('./planner');
23
+ const { isServerRevisionConflict } = require('./server-revision');
24
+ const {
25
+ extractInfoFromCookies,
26
+ loadAuthData,
27
+ resolveBaseUrl,
28
+ } = require('../core/utils');
29
+
30
+ const RECONCILIATION_CHOICES = Object.freeze([
31
+ 'inspect_remote_state',
32
+ 'provide_explicit_recovery_input',
33
+ 'stop',
34
+ ]);
35
+ const MANAGED_DECISION_CHOICES = Object.freeze([
36
+ 'keep_remote',
37
+ 'update_manifest',
38
+ 'stop',
39
+ ]);
40
+ const SECURITY_FAILURE_CODES = new Set([
41
+ 'SCHEMA_APPLY_LOCKED',
42
+ 'SCHEMA_APPLY_LOCK_FAILED',
43
+ 'SCHEMA_APPLY_LOCK_LOST',
44
+ 'SCHEMA_APPLY_PATH_UNSAFE',
45
+ 'SCHEMA_FORBIDDEN_FIELD',
46
+ 'SCHEMA_MANIFEST_PATH_UNSAFE',
47
+ 'SCHEMA_PAGE_SOURCE_PATH_UNSAFE',
48
+ 'SCHEMA_PLAN_STATE_INTEGRITY_FAILED',
49
+ 'SCHEMA_STATE_ENVIRONMENT_MISMATCH',
50
+ 'SCHEMA_STATE_FORBIDDEN_FIELD',
51
+ ]);
52
+ const VALIDATION_FAILURE_CODES = new Set([
53
+ 'SCHEMA_APPLY_JOURNAL_INVALID',
54
+ 'SCHEMA_DUPLICATE_KEY',
55
+ 'SCHEMA_INVALID',
56
+ 'SCHEMA_INVALID_ARGUMENTS',
57
+ 'SCHEMA_INVALID_KEY',
58
+ 'SCHEMA_INVALID_KIND',
59
+ 'SCHEMA_INVALID_REFERENCE',
60
+ 'SCHEMA_PAGE_FOUNDATION_INITIAL_PROFILE_INVALID',
61
+ 'SCHEMA_PAGE_FOUNDATION_OBSERVED_IDENTITY_INVALID',
62
+ 'SCHEMA_PAGE_FOUNDATION_SCHEMA_INVALID',
63
+ 'SCHEMA_PAGE_FOUNDATION_SHELL_PROFILE_INVALID',
64
+ 'SCHEMA_PAGE_FOUNDATION_TRANSITION_INVALID',
65
+ 'SCHEMA_PAGE_SOURCE_INVALID',
66
+ 'SCHEMA_PROCESS_NODE_PROPERTY_INVALID',
67
+ 'SCHEMA_STATE_INVALID',
68
+ 'SCHEMA_UNKNOWN_PROPERTY',
69
+ ]);
70
+ const VALIDATION_FAILURE_PREFIXES = Object.freeze([
71
+ 'SCHEMA_DEPENDENCY_',
72
+ 'SCHEMA_FIELD_',
73
+ 'SCHEMA_MANIFEST_',
74
+ 'SCHEMA_REFERENCE_',
75
+ ]);
76
+
77
+ function parseArgs(args) {
78
+ const [subCommand, ...rest] = args;
79
+ if (!subCommand || subCommand === '--help' || subCommand === '-h') {
80
+ return { help: true };
81
+ }
82
+ if (subCommand === 'validate') {
83
+ return parseValidateArgs(rest);
84
+ }
85
+ if (subCommand === 'plan') {
86
+ return parsePlanArgs(rest);
87
+ }
88
+ if (subCommand === 'apply') {
89
+ return parseApplyArgs(rest);
90
+ }
91
+
92
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Supported schema commands are "validate", "plan", and "apply".');
93
+ }
94
+
95
+ function parseValidateArgs(rest) {
96
+ const flags = new Set();
97
+ const positional = [];
98
+ for (const arg of rest) {
99
+ if (arg.startsWith('--')) {
100
+ if (arg !== '--json' && arg !== '--quiet') {
101
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Unknown schema validate option.', {
102
+ details: { option: arg },
103
+ });
104
+ }
105
+ flags.add(arg);
106
+ } else {
107
+ positional.push(arg);
108
+ }
109
+ }
110
+
111
+ if (positional.length !== 1) {
112
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Usage: openyida schema validate <manifest> --json --quiet.');
113
+ }
114
+
115
+ return {
116
+ subCommand: 'validate',
117
+ manifestPath: positional[0],
118
+ json: flags.has('--json'),
119
+ quiet: flags.has('--quiet'),
120
+ };
121
+ }
122
+
123
+ function parsePlanArgs(rest) {
124
+ const flags = new Set();
125
+ const positional = [];
126
+ let statePath;
127
+
128
+ for (let index = 0; index < rest.length; index++) {
129
+ const arg = rest[index];
130
+ if (arg === '--state') {
131
+ statePath = rest[index + 1];
132
+ index += 1;
133
+ if (!statePath || statePath.startsWith('--')) {
134
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Usage: openyida schema plan <manifest> --state <path> --json --quiet.');
135
+ }
136
+ } else if (arg.startsWith('--')) {
137
+ if (arg !== '--json' && arg !== '--quiet') {
138
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Unknown schema plan option.', {
139
+ details: { option: arg },
140
+ });
141
+ }
142
+ flags.add(arg);
143
+ } else {
144
+ positional.push(arg);
145
+ }
146
+ }
147
+
148
+ if (positional.length !== 1 || !statePath) {
149
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Usage: openyida schema plan <manifest> --state <path> --json --quiet.');
150
+ }
151
+
152
+ return {
153
+ subCommand: 'plan',
154
+ manifestPath: positional[0],
155
+ statePath,
156
+ json: flags.has('--json'),
157
+ quiet: flags.has('--quiet'),
158
+ };
159
+ }
160
+
161
+ function parseApplyArgs(rest) {
162
+ const flags = new Set();
163
+ const positional = [];
164
+ let statePath;
165
+ let planId;
166
+
167
+ for (let index = 0; index < rest.length; index++) {
168
+ const arg = rest[index];
169
+ if (arg === '--state' || arg === '--plan-id') {
170
+ const value = rest[index + 1];
171
+ index += 1;
172
+ if (!value || value.startsWith('--')) {
173
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Usage: openyida schema apply <manifest> --state <path> --plan-id <planId> --json --quiet.');
174
+ }
175
+ if (arg === '--state') {
176
+ statePath = value;
177
+ } else {
178
+ planId = value;
179
+ }
180
+ } else if (arg.startsWith('--')) {
181
+ if (arg !== '--json' && arg !== '--quiet') {
182
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Unknown schema apply option.', {
183
+ details: { option: arg },
184
+ });
185
+ }
186
+ flags.add(arg);
187
+ } else {
188
+ positional.push(arg);
189
+ }
190
+ }
191
+
192
+ if (
193
+ positional.length !== 1 ||
194
+ !statePath ||
195
+ !/^sha256:[a-f0-9]{64}$/.test(planId || '')
196
+ ) {
197
+ throw schemaError('SCHEMA_INVALID_ARGUMENTS', 'Usage: openyida schema apply <manifest> --state <path> --plan-id <planId> --json --quiet.');
198
+ }
199
+
200
+ return {
201
+ subCommand: 'apply',
202
+ manifestPath: positional[0],
203
+ statePath,
204
+ planId,
205
+ json: flags.has('--json'),
206
+ quiet: flags.has('--quiet'),
207
+ };
208
+ }
209
+
210
+ async function run(args = [], io = {}) {
211
+ const stdout = io.stdout || process.stdout;
212
+ const stderr = io.stderr || process.stderr;
213
+ const setExitCode = io.setExitCode !== false;
214
+
215
+ let options;
216
+ try {
217
+ options = parseArgs(args);
218
+ if (options.help) {
219
+ stdout.write('Usage: openyida schema <validate|plan|apply> <manifest> [--state <path>] [--plan-id <planId>] --json --quiet\n');
220
+ return undefined;
221
+ }
222
+
223
+ if (options.subCommand === 'apply') {
224
+ const payload = await runApply(options, io);
225
+ stdout.write(JSON.stringify(payload) + '\n');
226
+ return payload;
227
+ }
228
+
229
+ if (options.subCommand === 'plan') {
230
+ const payload = await runPlan(options, io);
231
+ stdout.write(JSON.stringify(payload) + '\n');
232
+ return payload;
233
+ }
234
+
235
+ const manifestOptions = createManifestLoadOptions(io);
236
+ const manifest = loadManifest(options.manifestPath, manifestOptions);
237
+ const result = normalizeManifest(manifest, manifestOptions);
238
+ const payload = toSuccessPayload(result);
239
+ stdout.write(JSON.stringify(payload) + '\n');
240
+ return payload;
241
+ } catch (error) {
242
+ const payloadKind = inferPayloadKind(args, options);
243
+ let payload = payloadKind === APPLY_KIND
244
+ ? toApplyFailurePayload(error)
245
+ : payloadKind === PLAN_KIND
246
+ ? toPlanFailurePayload(error)
247
+ : toFailurePayload(error);
248
+ if (payloadKind === APPLY_KIND && shouldAutomaticallyReplan(error) && options) {
249
+ payload = await attachAutomaticReplan(payload, error, options, io);
250
+ } else {
251
+ payload = attachFailureAction(payload, error);
252
+ }
253
+ const quiet = args.includes('--quiet') || process.argv.includes('--quiet') || (options && options.quiet);
254
+ stdout.write(JSON.stringify(payload) + '\n');
255
+ if (setExitCode) {
256
+ process.exitCode = 1;
257
+ }
258
+ if (!quiet && stderr && stderr.write) {
259
+ stderr.write(`${payload.error.code}: ${payload.error.message}\n`);
260
+ }
261
+ return payload;
262
+ }
263
+ }
264
+
265
+ async function runPlan(options, io) {
266
+ const registry = io.registry || createDefaultRegistry();
267
+ const runtime = createPlanRuntimeSnapshot(io);
268
+ const manifestOptions = createManifestLoadOptions(io);
269
+ const manifest = loadManifest(options.manifestPath, manifestOptions);
270
+ const normalizedResult = normalizeManifest(manifest, {
271
+ ...manifestOptions,
272
+ fsImpl: io.fsImpl,
273
+ registry,
274
+ });
275
+ const desiredResources = normalizedResult.normalized.resources;
276
+ const state = io.state || readState(options.statePath, {
277
+ environment: runtime.environment,
278
+ fsImpl: io.fsImpl,
279
+ manifestHash: normalizedResult.manifestHash,
280
+ registry,
281
+ });
282
+ const observableResources = selectObservableResources(desiredResources, state, { registry });
283
+ const observed = await resolveObservedResources(observableResources, state, {
284
+ io,
285
+ registry,
286
+ runtime,
287
+ });
288
+ return attachPlanAction(createPlan({
289
+ desiredResources,
290
+ manifestHash: normalizedResult.manifestHash,
291
+ observedResources: observed.resources,
292
+ state,
293
+ }, { registry }));
294
+ }
295
+
296
+ async function attachAutomaticReplan(payload, error, options, io) {
297
+ let replanned;
298
+ try {
299
+ replanned = await runPlan({
300
+ manifestPath: options.manifestPath,
301
+ statePath: options.statePath,
302
+ subCommand: 'plan',
303
+ }, io);
304
+ } catch (replanError) {
305
+ const replanFailure = attachFailureAction(toPlanFailurePayload(replanError), replanError);
306
+ return {
307
+ ...payload,
308
+ action: createAction(payload.error.code, 'automatic_replan_failed', {
309
+ blockText: replanFailure.error.message,
310
+ choices: replanFailure.action.choices,
311
+ nextAction: replanFailure.action.nextAction,
312
+ }),
313
+ replan: replanFailure,
314
+ };
315
+ }
316
+
317
+ const reviewedAction = replanned.action;
318
+ return {
319
+ ...payload,
320
+ action: createAction(payload.error.code, 'stale_replanned', {
321
+ blockText: payload.error.message,
322
+ choices: reviewedAction && reviewedAction.choices,
323
+ nextAction: reviewedAction && reviewedAction.nextAction || 'review_replanned_plan',
324
+ }),
325
+ replan: replanned,
326
+ };
327
+ }
328
+
329
+ function shouldAutomaticallyReplan(error) {
330
+ return !!(
331
+ error &&
332
+ (isFormOrPageServerRevisionConflict(error) || (
333
+ error.code === 'SCHEMA_APPLY_PLAN_STALE' &&
334
+ isTrustedSchemaError(error)
335
+ ))
336
+ );
337
+ }
338
+
339
+ function isFormOrPageServerRevisionConflict(error) {
340
+ return isServerRevisionConflict(error) &&
341
+ !!error.details &&
342
+ (error.details.resourceType === 'form' || error.details.resourceType === 'page');
343
+ }
344
+
345
+ function attachPlanAction(plan) {
346
+ const operations = new Set((plan.changes || []).map(change => change.operation));
347
+ if (operations.has('conflict') || operations.has('unmanaged')) {
348
+ return {
349
+ ...plan,
350
+ action: createAction('SCHEMA_APPLY_BLOCKED', 'managed_decision_required', {
351
+ blockText: safeApplyBlockText('SCHEMA_APPLY_BLOCKED'),
352
+ choices: MANAGED_DECISION_CHOICES,
353
+ nextAction: 'ask_human',
354
+ }),
355
+ };
356
+ }
357
+ if (operations.has('orphan')) {
358
+ return {
359
+ ...plan,
360
+ action: createAction('SCHEMA_APPLY_BLOCKED', 'orphan_blocked', {
361
+ blockText: safeApplyBlockText('SCHEMA_APPLY_BLOCKED'),
362
+ nextAction: 'resolve_orphan',
363
+ }),
364
+ };
365
+ }
366
+ return plan;
367
+ }
368
+
369
+ function attachFailureAction(payload, error) {
370
+ return {
371
+ ...payload,
372
+ action: classifyFailureAction(payload, error),
373
+ };
374
+ }
375
+
376
+ function classifyFailureAction(payload, _error) {
377
+ const errorCode = payload.error.code;
378
+ const blockText = payload.error.message;
379
+ const operation = payload.error.details && payload.error.details.operation;
380
+
381
+ if (errorCode === 'SCHEMA_RECONCILIATION_REQUIRED' || /UNCERTAIN/.test(errorCode)) {
382
+ return createAction(errorCode, 'reconciliation_required', {
383
+ blockText,
384
+ choices: RECONCILIATION_CHOICES,
385
+ nextAction: 'ask_human',
386
+ });
387
+ }
388
+ if (
389
+ errorCode === 'SCHEMA_STATE_RESOURCE_BINDING_MISSING' ||
390
+ errorCode === 'SCHEMA_OBSERVED_BINDING_MISSING' ||
391
+ errorCode === 'SCHEMA_OBSERVED_REFERENCE_AMBIGUOUS' ||
392
+ errorCode === 'SCHEMA_OBSERVED_REFERENCE_MISSING' ||
393
+ errorCode === 'SCHEMA_REMOTE_RESOURCE_MISSING'
394
+ ) {
395
+ return createAction(errorCode, 'managed_identity_decision_required', {
396
+ blockText,
397
+ choices: RECONCILIATION_CHOICES,
398
+ nextAction: 'ask_human',
399
+ });
400
+ }
401
+ if (
402
+ errorCode === 'SCHEMA_APPLY_BLOCKED' &&
403
+ (operation === 'conflict' || operation === 'unmanaged')
404
+ ) {
405
+ return createAction(errorCode, 'managed_decision_required', {
406
+ blockText,
407
+ choices: MANAGED_DECISION_CHOICES,
408
+ nextAction: 'ask_human',
409
+ });
410
+ }
411
+ if (errorCode === 'SCHEMA_APPLY_BLOCKED' && operation === 'orphan') {
412
+ return createAction(errorCode, 'orphan_blocked', {
413
+ blockText,
414
+ nextAction: 'resolve_orphan',
415
+ });
416
+ }
417
+ if (errorCode === 'SCHEMA_APPLY_JIT_CONFLICT') {
418
+ return createAction(errorCode, 'jit_conflict', {
419
+ blockText,
420
+ nextAction: 'run_schema_plan',
421
+ });
422
+ }
423
+ if (errorCode === 'SCHEMA_APPLY_PLAN_STALE') {
424
+ return createAction(errorCode, 'stale_blocked', {
425
+ blockText,
426
+ nextAction: 'run_schema_plan',
427
+ });
428
+ }
429
+ if (/UNSUPPORTED/.test(errorCode)) {
430
+ return createAction(errorCode, 'unsupported', {
431
+ blockText,
432
+ nextAction: 'remove_unsupported_manifest_content',
433
+ });
434
+ }
435
+ if (isSecurityFailure(errorCode)) {
436
+ return createAction(errorCode, 'security_failure', {
437
+ blockText,
438
+ nextAction: 'fix_security_boundary',
439
+ });
440
+ }
441
+ if (isValidationFailure(errorCode)) {
442
+ return createAction(errorCode, 'validation_failure', {
443
+ blockText,
444
+ nextAction: 'fix_manifest',
445
+ });
446
+ }
447
+ if (errorCode === 'SCHEMA_REMOTE_READ_FAILED' || errorCode === 'SCHEMA_REMOTE_PROJECT_FAILED') {
448
+ return createAction(errorCode, 'remote_read_blocked', {
449
+ blockText,
450
+ nextAction: 'check_remote_read',
451
+ });
452
+ }
453
+ return createAction(errorCode, 'blocked', {
454
+ blockText,
455
+ nextAction: 'stop',
456
+ });
457
+ }
458
+
459
+ function createAction(errorCode, classification, options) {
460
+ const action = {
461
+ errorCode,
462
+ classification,
463
+ safeToRetry: false,
464
+ nextAction: options.nextAction,
465
+ blockText: options.blockText,
466
+ };
467
+ if (Array.isArray(options.choices) && options.choices.length > 0) {
468
+ action.choices = options.choices.slice();
469
+ }
470
+ return action;
471
+ }
472
+
473
+ function safeApplyBlockText(code) {
474
+ return toApplyFailurePayload(schemaError(code, 'Schema apply is blocked.')).error.message;
475
+ }
476
+
477
+ function isSecurityFailure(code) {
478
+ return SECURITY_FAILURE_CODES.has(code);
479
+ }
480
+
481
+ function isValidationFailure(code) {
482
+ return VALIDATION_FAILURE_CODES.has(code) || hasCodePrefix(code, VALIDATION_FAILURE_PREFIXES);
483
+ }
484
+
485
+ function hasCodePrefix(code, prefixes) {
486
+ return prefixes.some(prefix => typeof code === 'string' && code.startsWith(prefix));
487
+ }
488
+
489
+ async function runApply(options, io) {
490
+ const registry = io.registry || createDefaultRegistry();
491
+ const runtime = createPlanRuntimeSnapshot(io);
492
+ if (!runtime.authRef && !hasInjectedServices(io.services)) {
493
+ throw schemaError('SCHEMA_STATE_ENVIRONMENT_REQUIRED', 'Schema apply requires environment identity and Yida auth context.', {
494
+ path: '/environment',
495
+ });
496
+ }
497
+ return applySchema({
498
+ authRef: runtime.authRef,
499
+ environment: runtime.environment,
500
+ expectedPlanId: options.planId,
501
+ loadDesired() {
502
+ const manifestOptions = createManifestLoadOptions(io);
503
+ const manifest = loadManifest(options.manifestPath, manifestOptions);
504
+ return normalizeManifest(manifest, {
505
+ ...manifestOptions,
506
+ fsImpl: io.fsImpl,
507
+ registry,
508
+ });
509
+ },
510
+ statePath: options.statePath,
511
+ workspaceRoot: io.projectRoot || process.cwd(),
512
+ }, {
513
+ fsImpl: io.fsImpl,
514
+ paths: io.applyPaths,
515
+ readObservedResources: io.readObservedResources,
516
+ formPostWriteReadbackRetry: options.formPostWriteReadbackRetry ?? io.formPostWriteReadbackRetry,
517
+ registry,
518
+ services: io.services,
519
+ });
520
+ }
521
+
522
+ function createManifestLoadOptions(io = {}) {
523
+ const options = {
524
+ workspaceRoot: io.projectRoot || process.cwd(),
525
+ };
526
+ if (io.fsImpl) {
527
+ options.fsImpl = io.fsImpl;
528
+ }
529
+ if (io.manifestLimits) {
530
+ options.limits = io.manifestLimits;
531
+ }
532
+ return options;
533
+ }
534
+
535
+ function hasInjectedServices(services) {
536
+ return !!(services && Object.keys(services).length > 0);
537
+ }
538
+
539
+ async function resolveObservedResources(resources, state, context) {
540
+ const io = context.io || {};
541
+ const runtime = context.runtime || createPlanRuntimeSnapshot(io);
542
+ if (io.observed) {
543
+ return io.observed;
544
+ }
545
+ if (io.observedResources) {
546
+ return { resources: io.observedResources };
547
+ }
548
+ if (typeof io.readObservedResources === 'function') {
549
+ return io.readObservedResources(resources, state, {
550
+ context: Object.assign({}, io.observedContext || {}, {
551
+ authRef: runtime.authRef,
552
+ environment: runtime.environment,
553
+ }),
554
+ registry: context.registry,
555
+ services: io.services,
556
+ });
557
+ }
558
+ if (!resources || resources.length === 0) {
559
+ return { resources: [] };
560
+ }
561
+ const authRef = runtime.authRef;
562
+ if (!authRef && !io.services) {
563
+ throw schemaError('SCHEMA_STATE_ENVIRONMENT_REQUIRED', 'Schema plan requires environment identity and read-only Yida auth context.', {
564
+ path: '/environment',
565
+ });
566
+ }
567
+ return readObservedResources(resources, state, {
568
+ context: Object.assign({}, io.observedContext || {}, {
569
+ authRef,
570
+ environment: runtime.environment,
571
+ }),
572
+ registry: context.registry,
573
+ services: io.services,
574
+ });
575
+ }
576
+
577
+ function createPlanRuntimeSnapshot(io) {
578
+ const authRef = resolvePlanAuthRef(io);
579
+ return {
580
+ authRef,
581
+ environment: resolvePlanEnvironment(io, authRef),
582
+ };
583
+ }
584
+
585
+ function resolvePlanEnvironment(io, authRef) {
586
+ if (io.environment) {
587
+ return io.environment;
588
+ }
589
+ const cookieData = io.cookieData !== undefined
590
+ ? io.cookieData
591
+ : authRef && authRef.cookieData;
592
+ const cookies = Array.isArray(cookieData && cookieData.cookies)
593
+ ? cookieData.cookies
594
+ : authRef && authRef.cookies || [];
595
+ const cookieInfo = extractInfoFromCookies(cookies);
596
+ return {
597
+ endpoint: authRef && authRef.baseUrl || resolveBaseUrl(cookieData || {}),
598
+ corpId: authRef && authRef.corpId || cookieData && (cookieData.corp_id || cookieData.corpId) || cookieInfo.corpId,
599
+ };
600
+ }
601
+
602
+ function resolvePlanAuthRef(io) {
603
+ if (io.authRef) {
604
+ return io.authRef;
605
+ }
606
+ const authData = loadAuthData(io.projectRoot);
607
+ if (authData && (authData.auth_mode === 'token' || authData.authMode === 'token')) {
608
+ return {
609
+ baseUrl: resolveBaseUrl(authData),
610
+ authData,
611
+ authMode: 'token',
612
+ authSource: authData.auth_source || authData.authSource || '',
613
+ corpId: authData.corp_id || authData.corpId || '',
614
+ userId: authData.user_id || authData.userId || '',
615
+ };
616
+ }
617
+ const cookieData = io.cookieData;
618
+ if (!cookieData || !Array.isArray(cookieData.cookies) || cookieData.cookies.length === 0) {
619
+ return null;
620
+ }
621
+ const cookieInfo = extractInfoFromCookies(cookieData.cookies);
622
+ return {
623
+ baseUrl: resolveBaseUrl(cookieData),
624
+ cookieData,
625
+ cookies: cookieData.cookies,
626
+ corpId: cookieData.corp_id || cookieData.corpId || cookieInfo.corpId || '',
627
+ csrfToken: cookieData.csrf_token || cookieData.csrfToken || cookieData._csrf_token || cookieInfo.csrfToken || '',
628
+ userId: cookieData.user_id || cookieData.userId || cookieData.staffId || cookieInfo.userId || '',
629
+ };
630
+ }
631
+
632
+ function inferPayloadKind(args, options) {
633
+ if ((options && options.subCommand === 'apply') || args[0] === 'apply') {
634
+ return APPLY_KIND;
635
+ }
636
+ if ((options && options.subCommand === 'plan') || args[0] === 'plan') {
637
+ return PLAN_KIND;
638
+ }
639
+ return undefined;
640
+ }
641
+
642
+ module.exports = {
643
+ parseArgs,
644
+ run,
645
+ };