create-windy 0.6.14 → 0.6.15

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 (160) hide show
  1. package/dist/cli.js +215 -24
  2. package/package.json +1 -1
  3. package/template/.agents/skills/windy-business-module/SKILL.md +58 -8
  4. package/template/.windy-template.json +2 -2
  5. package/template/apps/server/src/agent/client-session/attempt-authority.test.ts +162 -0
  6. package/template/apps/server/src/agent/client-session/attempt-authority.ts +191 -0
  7. package/template/apps/server/src/agent/client-session/bootstrap.ts +27 -11
  8. package/template/apps/server/src/agent/client-session/completion.ts +75 -24
  9. package/template/apps/server/src/agent/client-session/contracts.ts +23 -0
  10. package/template/apps/server/src/agent/client-session/creation.ts +103 -0
  11. package/template/apps/server/src/agent/client-session/digest.ts +11 -1
  12. package/template/apps/server/src/agent/client-session/drizzle-records.ts +150 -0
  13. package/template/apps/server/src/agent/client-session/drizzle-repository.integration.test.ts +30 -3
  14. package/template/apps/server/src/agent/client-session/drizzle-repository.ts +23 -132
  15. package/template/apps/server/src/agent/client-session/finalization.ts +99 -0
  16. package/template/apps/server/src/agent/client-session/host-auth.ts +22 -10
  17. package/template/apps/server/src/agent/client-session/host-revocation-composition.test.ts +77 -0
  18. package/template/apps/server/src/agent/client-session/host-revocation-composition.ts +28 -0
  19. package/template/apps/server/src/agent/client-session/launch-authority.contract.test.ts +21 -0
  20. package/template/apps/server/src/agent/client-session/manifest-admission.ts +11 -0
  21. package/template/apps/server/src/agent/client-session/service.test-support.ts +22 -0
  22. package/template/apps/server/src/agent/client-session/service.ts +104 -134
  23. package/template/apps/server/src/agent/client-session/terminal-digest.test.ts +23 -0
  24. package/template/apps/server/src/agent/client-workflow-artifact/active-blob-references.ts +8 -0
  25. package/template/apps/server/src/agent/client-workflow-artifact/artifact-builder.ts +60 -0
  26. package/template/apps/server/src/agent/client-workflow-artifact/authority-current.ts +59 -0
  27. package/template/apps/server/src/agent/client-workflow-artifact/binding-registry.test.ts +189 -0
  28. package/template/apps/server/src/agent/client-workflow-artifact/binding-registry.ts +153 -0
  29. package/template/apps/server/src/agent/client-workflow-artifact/bootstrap.ts +77 -0
  30. package/template/apps/server/src/agent/client-workflow-artifact/cancellation.ts +47 -0
  31. package/template/apps/server/src/agent/client-workflow-artifact/completed-recovery.ts +31 -0
  32. package/template/apps/server/src/agent/client-workflow-artifact/contracts.ts +104 -0
  33. package/template/apps/server/src/agent/client-workflow-artifact/drizzle-locks.ts +30 -0
  34. package/template/apps/server/src/agent/client-workflow-artifact/drizzle-mapper.ts +138 -0
  35. package/template/apps/server/src/agent/client-workflow-artifact/drizzle-repository.ts +346 -0
  36. package/template/apps/server/src/agent/client-workflow-artifact/error.ts +21 -0
  37. package/template/apps/server/src/agent/client-workflow-artifact/handler.ts +167 -0
  38. package/template/apps/server/src/agent/client-workflow-artifact/host-revocation.ts +29 -0
  39. package/template/apps/server/src/agent/client-workflow-artifact/in-memory-repository.ts +232 -0
  40. package/template/apps/server/src/agent/client-workflow-artifact/job-port.ts +101 -0
  41. package/template/apps/server/src/agent/client-workflow-artifact/presentation.ts +41 -0
  42. package/template/apps/server/src/agent/client-workflow-artifact/recovery.contract.test.ts +253 -0
  43. package/template/apps/server/src/agent/client-workflow-artifact/release-binding.ts +85 -0
  44. package/template/apps/server/src/agent/client-workflow-artifact/repository.test.ts +204 -0
  45. package/template/apps/server/src/agent/client-workflow-artifact/repository.ts +97 -0
  46. package/template/apps/server/src/agent/client-workflow-artifact/routes-handler.contract.test.ts +201 -0
  47. package/template/apps/server/src/agent/client-workflow-artifact/routes.ts +161 -0
  48. package/template/apps/server/src/agent/client-workflow-artifact/runtime-composition.ts +101 -0
  49. package/template/apps/server/src/agent/client-workflow-artifact/scope-authority.ts +39 -0
  50. package/template/apps/server/src/agent/client-workflow-artifact/service-authorization.ts +117 -0
  51. package/template/apps/server/src/agent/client-workflow-artifact/service-support.ts +28 -0
  52. package/template/apps/server/src/agent/client-workflow-artifact/service.contract.test.ts +345 -0
  53. package/template/apps/server/src/agent/client-workflow-artifact/service.ts +350 -0
  54. package/template/apps/server/src/agent/client-workflow-artifact/session-boundary.ts +39 -0
  55. package/template/apps/server/src/agent/client-workflow-artifact/source-access.contract.test.ts +98 -0
  56. package/template/apps/server/src/agent/client-workflow-artifact/source-access.ts +80 -0
  57. package/template/apps/server/src/agent/client-workflow-artifact/takeover.ts +122 -0
  58. package/template/apps/server/src/agent/client-workflow-artifact/task-authority.contract.test.ts +97 -0
  59. package/template/apps/server/src/agent/client-workflow-artifact/task-authority.ts +147 -0
  60. package/template/apps/server/src/agent/client-workflow-artifact/terminal-authority.contract.test.ts +100 -0
  61. package/template/apps/server/src/agent/client-workflow-artifact/terminal-replay.ts +31 -0
  62. package/template/apps/server/src/agent/client-workflow-artifact/terminal-seal.ts +211 -0
  63. package/template/apps/server/src/agent/client-workflow-artifact/workflow-artifact.test-support.ts +173 -0
  64. package/template/apps/server/src/agent/client-workflow-artifact/workflow-loader.contract.test.ts +254 -0
  65. package/template/apps/server/src/agent/client-workflow-artifact/workflow-loader.ts +285 -0
  66. package/template/apps/server/src/agent/run-facade.test-support.ts +17 -4
  67. package/template/apps/server/src/agent/run-facade.test.ts +16 -0
  68. package/template/apps/server/src/agent/run-session-authorization.ts +12 -10
  69. package/template/apps/server/src/agent/runtime-bootstrap-input.ts +5 -1
  70. package/template/apps/server/src/agent/runtime-bootstrap.ts +33 -33
  71. package/template/apps/server/src/agent/runtime-public-ports.ts +40 -0
  72. package/template/apps/server/src/agent/session-invalidation/contracts.ts +25 -26
  73. package/template/apps/server/src/agent/session-projection-access.ts +31 -19
  74. package/template/apps/server/src/agent/unavailable-routes.ts +21 -0
  75. package/template/apps/server/src/agent/workflow-runtime-bootstrap.ts +2 -0
  76. package/template/apps/server/src/agent-workflow/artifact-source-authorization.ts +12 -6
  77. package/template/apps/server/src/agent-workflow/command-facade.ts +70 -11
  78. package/template/apps/server/src/agent-workflow/drizzle-artifact-port.ts +9 -9
  79. package/template/apps/server/src/agent-workflow/drizzle-delegation-completion.ts +1 -1
  80. package/template/apps/server/src/agent-workflow/platform-node-adapters.ts +14 -6
  81. package/template/apps/server/src/agent-workflow/project-launch-authority.contract.test.ts +53 -0
  82. package/template/apps/server/src/agent-workflow/project-launch-authority.ts +92 -0
  83. package/template/apps/server/src/agent-workflow/runtime-composition.ts +30 -14
  84. package/template/apps/server/src/app/agent-runtime-composition.ts +6 -1
  85. package/template/apps/server/src/app/client-agent-workflow-artifact-binding.ts +14 -0
  86. package/template/apps/server/src/application-services.ts +6 -0
  87. package/template/apps/server/src/data-access/scope-containment.test.ts +31 -0
  88. package/template/apps/server/src/data-access/scope-containment.ts +48 -0
  89. package/template/apps/server/src/jobs/artifact-publication.test.ts +192 -0
  90. package/template/apps/server/src/jobs/artifact-publication.ts +56 -0
  91. package/template/apps/server/src/jobs/artifact-publisher.ts +101 -0
  92. package/template/apps/server/src/jobs/drizzle-artifact.ts +73 -1
  93. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +14 -1
  94. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +65 -0
  95. package/template/apps/server/src/jobs/drizzle-repository.integration.test.ts +1 -0
  96. package/template/apps/server/src/jobs/execution-repository.ts +28 -0
  97. package/template/apps/server/src/jobs/execution.test.ts +3 -1
  98. package/template/apps/server/src/jobs/in-memory-execution.ts +16 -0
  99. package/template/apps/server/src/jobs/in-memory-lease.ts +45 -1
  100. package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +2 -0
  101. package/template/apps/server/src/jobs/postgres-cleanup-contract.test.ts +58 -0
  102. package/template/apps/server/src/jobs/worker.ts +8 -14
  103. package/template/apps/server/src/module-host/background-ai-unavailable.ts +18 -0
  104. package/template/apps/server/src/module-host/durable-context.ts +19 -22
  105. package/template/apps/server/src/module-host/implementation-completeness.test.ts +80 -1
  106. package/template/apps/server/src/module-host/implementation-completeness.ts +28 -1
  107. package/template/apps/server/src/module-host/request-context.ts +32 -8
  108. package/template/apps/server/src/module-host/storage-port.ts +3 -0
  109. package/template/apps/server/src/module-host/workflow-input-artifact-port.test.ts +104 -0
  110. package/template/apps/server/src/module-host/workflow-input-artifact-port.ts +229 -0
  111. package/template/apps/server/src/module-host/workflow-input-materialization.test.ts +163 -0
  112. package/template/apps/server/src/module-host/workflow-input-materialization.ts +161 -0
  113. package/template/apps/server/src/workflow/drizzle-repository.integration.test.ts +1 -0
  114. package/template/docs/architecture/agent-workflow.md +13 -2
  115. package/template/docs/architecture/durable-jobs.md +7 -0
  116. package/template/docs/operations/agent-session-memory.md +2 -1
  117. package/template/docs/operations/agent-session-troubleshooting.md +87 -2
  118. package/template/docs/operations/agent-workflow-recovery.md +25 -14
  119. package/template/docs/platform/client-agent-session.md +148 -2
  120. package/template/packages/ai-client/package.json +2 -1
  121. package/template/packages/ai-client/src/client-agent/index.ts +1 -0
  122. package/template/packages/ai-client/src/client-agent/workflow-artifact/contracts.ts +85 -0
  123. package/template/packages/ai-client/src/client-agent/workflow-artifact/http.test.ts +49 -0
  124. package/template/packages/ai-client/src/client-agent/workflow-artifact/http.ts +82 -0
  125. package/template/packages/ai-client/src/client-agent/workflow-artifact/index.ts +3 -0
  126. package/template/packages/ai-client/src/client-agent/workflow-artifact/validation.test.ts +154 -0
  127. package/template/packages/ai-client/src/client-agent/workflow-artifact/validation.ts +332 -0
  128. package/template/packages/database/drizzle/0062_client_agent_workflow_artifact.sql +63 -0
  129. package/template/packages/database/drizzle/meta/0062_snapshot.json +14839 -0
  130. package/template/packages/database/drizzle/meta/_journal.json +7 -0
  131. package/template/packages/database/package.json +1 -1
  132. package/template/packages/database/src/agent-runtime-schema.test.ts +177 -0
  133. package/template/packages/database/src/schema/client-agent-workflow-artifact.ts +158 -0
  134. package/template/packages/database/src/schema/index.ts +1 -0
  135. package/template/packages/jobs/package.json +1 -1
  136. package/template/packages/jobs/src/handlers.test.ts +10 -0
  137. package/template/packages/jobs/src/handlers.ts +28 -11
  138. package/template/packages/modules/package.json +1 -1
  139. package/template/packages/modules/src/ai-client-execution-policy.ts +6 -0
  140. package/template/packages/modules/src/manifest.ts +2 -0
  141. package/template/packages/modules/src/system-agent-audit-actions.ts +3 -0
  142. package/template/packages/modules/src/system-ai-api-bindings.ts +15 -0
  143. package/template/packages/modules/src/system-audit-actions.ts +15 -0
  144. package/template/packages/server-sdk/index.ts +52 -0
  145. package/template/packages/server-sdk/package.json +5 -1
  146. package/template/packages/server-sdk/src/client-agent-session.ts +13 -1
  147. package/template/packages/server-sdk/src/client-agent-workflow-artifact.contract.test.ts +113 -0
  148. package/template/packages/server-sdk/src/client-agent-workflow-artifact.ts +183 -0
  149. package/template/packages/server-sdk/src/durable-handler.ts +7 -0
  150. package/template/packages/server-sdk/src/request-context.ts +7 -0
  151. package/template/packages/server-sdk/src/workflow-input-artifact-port.ts +104 -0
  152. package/template/packages/server-sdk/src/workflow-input-artifact-validation.contract.test.ts +124 -0
  153. package/template/packages/server-sdk/src/workflow-input-artifact-validation.ts +347 -0
  154. package/template/packages/server-sdk/src/workflow-input-materialization-handler.ts +43 -0
  155. package/template/packages/storage/package.json +1 -1
  156. package/template/packages/storage/src/blob-store-put-once.test.ts +70 -0
  157. package/template/packages/storage/src/blob-store.ts +9 -0
  158. package/template/packages/storage/src/local-file-blob-put-once.ts +120 -0
  159. package/template/packages/storage/src/local-file-blob-store.ts +53 -1
  160. package/template/packages/storage/src/memory-blob-store.ts +73 -33
package/dist/cli.js CHANGED
@@ -304,6 +304,7 @@ var agentOptionalModule = {
304
304
  "apps/server/src/app/ai-screenshot-intake-binding.ts",
305
305
  "apps/server/src/app/agent-runtime-composition.ts",
306
306
  "apps/server/src/app/client-agent-host-auth-binding.ts",
307
+ "apps/server/src/app/client-agent-workflow-artifact-binding.ts",
307
308
  "apps/server/src/app/document-output-artifact-bindings.ts",
308
309
  "apps/server/src/app/speech-output-artifact-bindings.ts",
309
310
  "apps/server/src/ai-artifact",
@@ -316,6 +317,10 @@ var agentOptionalModule = {
316
317
  "apps/server/src/module-host/ai-operation-port.test.ts",
317
318
  "apps/server/src/module-host/agent-session-memory-port.ts",
318
319
  "apps/server/src/module-host/agent-source-invalidation-port.ts",
320
+ "apps/server/src/module-host/workflow-input-artifact-port.ts",
321
+ "apps/server/src/module-host/workflow-input-artifact-port.test.ts",
322
+ "apps/server/src/module-host/workflow-input-materialization.ts",
323
+ "apps/server/src/module-host/workflow-input-materialization.test.ts",
319
324
  "apps/server/src/module-host/tool-handlers.ts",
320
325
  "apps/server/src/module-host/tool-handlers.test.ts",
321
326
  "apps/server/src/module-host/module-secret-tool-boundary.test.ts",
@@ -346,6 +351,12 @@ var agentOptionalModule = {
346
351
  "packages/modules/src/system-ai-api-bindings.ts",
347
352
  "packages/server-sdk/src/system-agent-supervisor.ts",
348
353
  "packages/server-sdk/src/system-agent-supervisor.test.ts",
354
+ "packages/server-sdk/src/client-agent-workflow-artifact.ts",
355
+ "packages/server-sdk/src/client-agent-workflow-artifact.contract.test.ts",
356
+ "packages/server-sdk/src/workflow-input-artifact-port.ts",
357
+ "packages/server-sdk/src/workflow-input-artifact-validation.ts",
358
+ "packages/server-sdk/src/workflow-input-artifact-validation.contract.test.ts",
359
+ "packages/server-sdk/src/workflow-input-materialization-handler.ts",
349
360
  "packages/database/src/agent-runtime-schema.test.ts",
350
361
  "packages/database/src/ai-output-artifacts.test.ts",
351
362
  "packages/shared/src/agent-workflow-definition.ts",
@@ -362,6 +373,7 @@ var agentOptionalModule = {
362
373
  "docs/adr/0003-agent-session-event-source.md",
363
374
  "docs/architecture/agent-harness.md",
364
375
  "docs/architecture/agent-workflow.md",
376
+ "docs/architecture/durable-jobs.md",
365
377
  "docs/architecture/ai-egress.md",
366
378
  "docs/architecture/ai-runtime-readiness.md",
367
379
  "docs/architecture/ai-runtime.md",
@@ -396,6 +408,7 @@ var agentOptionalModule = {
396
408
  "packages/database/src/schema/agent-workflow-effects.ts",
397
409
  "packages/database/src/schema/agent-workflow-evaluation.ts",
398
410
  "packages/database/src/schema/client-agent.ts",
411
+ "packages/database/src/schema/client-agent-workflow-artifact.ts",
399
412
  "packages/database/src/schema/embedding-runtime.ts",
400
413
  "packages/database/src/schema/ai-output-artifacts.ts"
401
414
  ],
@@ -410,6 +423,7 @@ var agentOptionalModule = {
410
423
  "agent_runtime_report_attempts",
411
424
  "client_agent_sessions",
412
425
  "client_agent_receipts",
426
+ "client_agent_workflow_artifacts",
413
427
  "embedding_run_bindings",
414
428
  "ai_output_artifact_scopes",
415
429
  "ai_output_artifacts",
@@ -439,7 +453,8 @@ var agentOptionalModule = {
439
453
  "idx_agent_context_sources_origin",
440
454
  "idx_agent_memory_sources_origin",
441
455
  "uk_agent_source_invalidations_sequence",
442
- "agent_workflow_"
456
+ "agent_workflow_",
457
+ "client_agent_workflow_"
443
458
  ]
444
459
  };
445
460
 
@@ -8452,6 +8467,11 @@ var recipes = [
8452
8467
  id: "starter-0.6.13-to-0.6.14",
8453
8468
  from: "0.6.13",
8454
8469
  to: "0.6.14"
8470
+ },
8471
+ {
8472
+ id: "starter-0.6.14-to-0.6.15",
8473
+ from: "0.6.14",
8474
+ to: "0.6.15"
8455
8475
  }
8456
8476
  ];
8457
8477
  function resolveRecipeChain(sourceVersion, targetVersion) {
@@ -9813,6 +9833,163 @@ function conflict(path2, reason, expectedProjectContent) {
9813
9833
  };
9814
9834
  }
9815
9835
 
9836
+ // src/update/recipe-project-owned-client-workflow.ts
9837
+ var clientWorkflowCompositionPath = "apps/server/src/app/agent-runtime-composition.ts";
9838
+ var clientWorkflowBindingPath = "apps/server/src/app/client-agent-workflow-artifact-binding.ts";
9839
+ var legacyDefaultBinding = `import type { ModuleClientAgentWorkflowArtifactProjectBinding } from "@southwind-ai/server-sdk";
9840
+
9841
+ /**
9842
+ * Project-owned Workflow -> PageAgent \u7ED1\u5B9A\u3002Starter \u9ED8\u8BA4\u7A7A\u6570\u7EC4\u5E76 fail closed\uFF1B
9843
+ * \u4EA7\u54C1\u53EA\u4E3A\u5DF2\u5BA1\u6838\u3001\u5DF2\u53D1\u5E03\u7684\u56FA\u5B9A Workflow Job node \u589E\u52A0\u9759\u6001\u7ED1\u5B9A\u3002
9844
+ */
9845
+ export const projectClientAgentWorkflowArtifactBindings: readonly ModuleClientAgentWorkflowArtifactProjectBinding[] =
9846
+ [];
9847
+ `;
9848
+ var immutableReleaseDefaultBinding = `import type { ModuleClientAgentWorkflowArtifactProjectBinding } from "@southwind-ai/server-sdk";
9849
+
9850
+ /**
9851
+ * Project-owned Workflow -> PageAgent \u7ED1\u5B9A\u3002Starter \u9ED8\u8BA4\u7A7A\u6570\u7EC4\u5E76 fail closed\uFF1B
9852
+ * \u4EA7\u54C1\u53EA\u4E3A\u5DF2\u5BA1\u6838\u3001\u5DF2\u53D1\u5E03\u7684\u56FA\u5B9A Workflow Job node \u589E\u52A0\u9759\u6001\u7ED1\u5B9A\u3002Operation \u5FC5\u987B\u58F0\u660E
9853
+ * \`clientExecution.launchAuthority="workflow-artifact"\`\uFF1Bbinding \u5FC5\u987B\u767B\u8BB0 Immutable
9854
+ * canonical \`releaseDigest\`\u3001scope containment contract v1\uFF0C\u4EE5\u53CA project launch\u3001client task\u3001terminal
9855
+ * authority version/digest\u3002launch authority \u4ECE Host \u5F53\u524D scope \u663E\u5F0F\u6536\u7A84\uFF1Bterminal authority
9856
+ * \u540C\u65F6\u590D\u9A8C Host \u91CD\u6388\u6743\u5E76\u6253\u5F00\u7684 canonical input artifacts\u3002project preset \u4F7F\u7528
9857
+ * runtime.agentWorkflowProjects\uFF1B\u666E\u901A routes \u6C38\u8FDC\u4E0D\u80FD\u53D1\u5E03/\u542F\u52A8\u53D7\u4FDD\u62A4 Workflow\u3002
9858
+ * \u53D1\u5E03 Release \u6216 authority contract \u540E\u5FC5\u987B\u91CD\u65B0\u5BA1\u6838\u5E76\u663E\u5F0F\u66F4\u65B0\u3002
9859
+ */
9860
+ export const projectClientAgentWorkflowArtifactBindings: readonly ModuleClientAgentWorkflowArtifactProjectBinding[] =
9861
+ [];
9862
+ `;
9863
+ var immutableReleaseCompositionHash = "98c23266799311cf26c160374aad738456888f3c04f40f3667122e28b3e8e188";
9864
+ var hostAuthImport = 'import { projectClientAgentHostAuthAdapter } from "./client-agent-host-auth-binding.js";';
9865
+ var workflowArtifactImport = 'import { projectClientAgentWorkflowArtifactBindings } from "./client-agent-workflow-artifact-binding.js";';
9866
+ var oldOmit = ' "clientAgentHostAuth" | "screenshotPageRegistry"';
9867
+ var newOmit = ` | "clientAgentHostAuth"
9868
+ | "clientAgentWorkflowArtifactBindings"
9869
+ | "screenshotPageRegistry"`;
9870
+ var hostAuthProperty = " clientAgentHostAuth: projectClientAgentHostAuthAdapter,";
9871
+ var workflowArtifactProperty = ` clientAgentWorkflowArtifactBindings:
9872
+ projectClientAgentWorkflowArtifactBindings,`;
9873
+ function planClientWorkflowProjectOwned(input) {
9874
+ return input.path === clientWorkflowBindingPath ? planBinding(input) : planComposition(input);
9875
+ }
9876
+ function planBinding(input) {
9877
+ if (!input.target)
9878
+ return conflict2(input, "\u76EE\u6807\u7248\u672C\u7F3A\u5C11 Workflow binding seam");
9879
+ const target = decode(input.target);
9880
+ if (target !== immutableReleaseDefaultBinding) {
9881
+ return conflict2(input, "\u76EE\u6807\u7248\u672C Workflow binding seam \u5951\u7EA6\u65E0\u6548");
9882
+ }
9883
+ if (!input.ours) {
9884
+ return ready2(input, "create", "\u65B0\u589E\u9ED8\u8BA4\u5173\u95ED\u7684 Workflow binding seam", input.target);
9885
+ }
9886
+ const source = decode(input.ours);
9887
+ if (source === target) {
9888
+ return ready2(input, "preserve", "\u5DF2\u5305\u542B immutable release binding seam");
9889
+ }
9890
+ if (source !== legacyDefaultBinding) {
9891
+ return conflict2(input, "Workflow binding seam \u4E0D\u662F 0.6.14 \u9ED8\u8BA4\u7A7A\u7248\u672C");
9892
+ }
9893
+ return ready2(input, "update", "\u5347\u7EA7\u9ED8\u8BA4\u7A7A Workflow binding seam", input.target);
9894
+ }
9895
+ function planComposition(input) {
9896
+ if (!input.target) {
9897
+ return conflict2(input, "\u76EE\u6807\u7248\u672C\u7F3A\u5C11 Agent Runtime Composition");
9898
+ }
9899
+ const target = decode(input.target);
9900
+ if (hashContent(target) !== immutableReleaseCompositionHash) {
9901
+ return conflict2(input, "\u76EE\u6807\u7248\u672C Agent Runtime Composition \u5951\u7EA6\u65E0\u6548");
9902
+ }
9903
+ if (!input.ours) {
9904
+ return ready2(input, "create", "\u65B0\u589E Agent Runtime Composition", input.target);
9905
+ }
9906
+ const source = decode(input.ours);
9907
+ if (source === target) {
9908
+ return ready2(input, "preserve", "\u5DF2\u88C5\u914D Workflow Artifact binding");
9909
+ }
9910
+ if ([workflowArtifactImport, newOmit, workflowArtifactProperty].some((value) => source.includes(value))) {
9911
+ return conflict2(input, "Agent Runtime Composition \u53EA\u5305\u542B\u90E8\u5206\u76EE\u6807\u88C5\u914D");
9912
+ }
9913
+ const runtimeConflict = validateLegacyRuntimeObject(source);
9914
+ if (runtimeConflict)
9915
+ return conflict2(input, runtimeConflict);
9916
+ const replacements2 = [
9917
+ {
9918
+ anchor: hostAuthImport,
9919
+ value: `${hostAuthImport}
9920
+ ${workflowArtifactImport}`
9921
+ },
9922
+ {
9923
+ anchor: oldOmit,
9924
+ value: newOmit
9925
+ },
9926
+ {
9927
+ anchor: hostAuthProperty,
9928
+ value: `${hostAuthProperty}
9929
+ ${workflowArtifactProperty}`
9930
+ }
9931
+ ];
9932
+ let content = source;
9933
+ for (const replacement of replacements2) {
9934
+ if (occurrences(content, replacement.anchor) !== 1) {
9935
+ return conflict2(input, `Agent Runtime Composition \u951A\u70B9\u4E0D\u552F\u4E00\uFF1A${replacement.anchor}`);
9936
+ }
9937
+ content = content.replace(replacement.anchor, replacement.value);
9938
+ }
9939
+ return ready2(input, "update", "\u88C5\u914D Workflow Artifact project binding", new TextEncoder().encode(content));
9940
+ }
9941
+ function ready2(input, action, reason, content) {
9942
+ return {
9943
+ path: input.path,
9944
+ ownership: "project-owned",
9945
+ action,
9946
+ reason,
9947
+ expectedProjectContent: input.expected,
9948
+ content
9949
+ };
9950
+ }
9951
+ function conflict2(input, message) {
9952
+ return {
9953
+ path: input.path,
9954
+ ownership: "project-owned",
9955
+ action: "preserve",
9956
+ reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
9957
+ expectedProjectContent: input.expected,
9958
+ conflict: message
9959
+ };
9960
+ }
9961
+ function decode(content) {
9962
+ return new TextDecoder().decode(content);
9963
+ }
9964
+ function occurrences(source, value) {
9965
+ return source.split(value).length - 1;
9966
+ }
9967
+ function validateLegacyRuntimeObject(source) {
9968
+ const startAnchor = ` const runtime = registerAgentPlatformRuntime({
9969
+ ...input,`;
9970
+ const endAnchor = `
9971
+ });`;
9972
+ if (occurrences(source, startAnchor) !== 1 || occurrences(source, endAnchor) !== 1) {
9973
+ return "Agent Runtime register object \u951A\u70B9\u4E0D\u552F\u4E00";
9974
+ }
9975
+ const start = source.indexOf(startAnchor);
9976
+ const end = source.indexOf(endAnchor, start + startAnchor.length);
9977
+ if (end < 0)
9978
+ return "Agent Runtime register object \u7ED3\u675F\u951A\u70B9\u7F3A\u5931";
9979
+ const object = source.slice(start, end);
9980
+ const host = object.indexOf(hostAuthProperty);
9981
+ if (host < 0)
9982
+ return "Agent Runtime Host Auth property \u951A\u70B9\u7F3A\u5931";
9983
+ const tail = object.slice(host + hostAuthProperty.length);
9984
+ if (/^\s*\.\.\./m.test(tail)) {
9985
+ return "Workflow binding \u63D2\u5165\u70B9\u540E\u5B58\u5728\u53EF\u8986\u76D6\u5B83\u7684 spread";
9986
+ }
9987
+ if (/["']clientAgentWorkflowArtifactBindings["']\s*:/.test(object) || /\[\s*["']clientAgentWorkflowArtifactBindings["']\s*\]/.test(object)) {
9988
+ return "Agent Runtime \u5DF2\u5B58\u5728\u52A8\u6001 Workflow binding property";
9989
+ }
9990
+ return;
9991
+ }
9992
+
9816
9993
  // src/update/recipe-project-owned-trajectory-test.ts
9817
9994
  var legacyAnchor = /^(\s*)traceId: "trace_1",\n\1attemptItems: \[$/gm;
9818
9995
  var migratedAnchor = /^(\s*)traceId: "trace_1",\n\1trajectory: \{\n\1 {2}available: true,\n\1 {2}events: \[\],\n\1\},\n\1attemptItems: \[$/gm;
@@ -9854,20 +10031,33 @@ var managedPathsByRecipe = {
9854
10031
  "apps/web/src/router/index.ts",
9855
10032
  "apps/web/src/router/platform-admin-route-bindings.ts",
9856
10033
  "apps/web/src/services/ai-runtime-api.ts"
10034
+ ],
10035
+ "starter-0.6.14-to-0.6.15": [
10036
+ clientWorkflowCompositionPath,
10037
+ clientWorkflowBindingPath
9857
10038
  ]
9858
10039
  };
9859
10040
  function recipeManagedProjectOwnedPaths(recipes2) {
9860
10041
  return new Set(recipes2.flatMap((recipe) => managedPathsByRecipe[recipe] ?? []));
9861
10042
  }
10043
+ function recipeCanManageMissingProjectOwnedPath(path2) {
10044
+ return path2 === clientWorkflowCompositionPath || path2 === clientWorkflowBindingPath;
10045
+ }
9862
10046
  async function planRecipeProjectOwned(input) {
10047
+ if (input.path === clientWorkflowCompositionPath || input.path === clientWorkflowBindingPath) {
10048
+ if (!input.target) {
10049
+ return conflict3(input, "\u7248\u672C recipe \u6240\u9700\u7684\u76EE\u6807\u6587\u4EF6\u7F3A\u5931");
10050
+ }
10051
+ return planClientWorkflowProjectOwned({ ...input, target: input.target });
10052
+ }
9863
10053
  if (!input.ours) {
9864
- return conflict2(input, "\u7248\u672C recipe \u6240\u9700\u7684\u9879\u76EE\u951A\u70B9\u7F3A\u5931");
10054
+ return conflict3(input, "\u7248\u672C recipe \u6240\u9700\u7684\u9879\u76EE\u951A\u70B9\u7F3A\u5931");
9865
10055
  }
9866
10056
  const source = new TextDecoder().decode(input.ours);
9867
10057
  const target = input.target ? new TextDecoder().decode(input.target) : undefined;
9868
10058
  const transformed = transformProjectOwnedAnchor(input.path, source, target);
9869
10059
  if ("error" in transformed)
9870
- return conflict2(input, transformed.error);
10060
+ return conflict3(input, transformed.error);
9871
10061
  if (transformed.content === source) {
9872
10062
  return preserve(input, "\u5DF2\u5305\u542B\u7248\u672C recipe \u76EE\u6807\u5185\u5BB9");
9873
10063
  }
@@ -10053,7 +10243,7 @@ function update(input, content) {
10053
10243
  content
10054
10244
  };
10055
10245
  }
10056
- function conflict2(input, message) {
10246
+ function conflict3(input, message) {
10057
10247
  return {
10058
10248
  path: input.path,
10059
10249
  ownership: "project-owned",
@@ -10073,7 +10263,8 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10073
10263
  const ownership = source?.ownership ?? target?.ownership ?? classifyOwnership(path2);
10074
10264
  const expected = expectationForSnapshot(ours);
10075
10265
  if (ownership === "project-owned") {
10076
- if (manageRecipeProjectOwned && source) {
10266
+ const hasExistingRecipeSource = source !== undefined && source.state !== "missing" && ours !== undefined;
10267
+ if (manageRecipeProjectOwned && target && (hasExistingRecipeSource || recipeCanManageMissingProjectOwnedPath(path2))) {
10077
10268
  return planRecipeProjectOwned({ path: path2, ours, target: theirs, expected });
10078
10269
  }
10079
10270
  if (manageGeneratedProjectOwned) {
@@ -10083,29 +10274,29 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10083
10274
  }
10084
10275
  if (path2.startsWith("packages/database/drizzle/") && path2.endsWith(".sql")) {
10085
10276
  if (source && !target) {
10086
- return conflict3(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
10277
+ return conflict4(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
10087
10278
  }
10088
10279
  if (source && target && source.hash !== target.hash) {
10089
- return conflict3(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
10280
+ return conflict4(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
10090
10281
  }
10091
10282
  }
10092
10283
  if (!source && target) {
10093
10284
  if (!ours) {
10094
10285
  return readyPlannedFile(path2, ownership, "create", "\u76EE\u6807\u7248\u672C\u65B0\u589E", expected, theirs);
10095
10286
  }
10096
- return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict3(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
10287
+ return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict4(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
10097
10288
  }
10098
10289
  if (source && !target) {
10099
10290
  if (!ours) {
10100
10291
  return readyPlannedFile(path2, ownership, "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
10101
10292
  }
10102
- return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict3(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
10293
+ return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict4(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
10103
10294
  }
10104
10295
  if (source && target && !ours) {
10105
10296
  return readyPlannedFile(path2, "project-owned", "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
10106
10297
  }
10107
10298
  if (!source || !target || !ours || !theirs) {
10108
- return conflict3(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
10299
+ return conflict4(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
10109
10300
  }
10110
10301
  const oursChanged = hashContent(ours) !== source.hash;
10111
10302
  const sourceArtifactHash = artifactHashOf(source);
@@ -10119,7 +10310,7 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10119
10310
  });
10120
10311
  if (forceTargetBaseline && path2.endsWith("package.json") && base) {
10121
10312
  const merged = mergePackageJson(base, ours, theirs);
10122
- return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10313
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict4(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10123
10314
  }
10124
10315
  if (forceTargetBaseline) {
10125
10316
  return readyPlannedFile(path2, ownership, "update", "\u5F3A\u5236\u91C7\u7528\u76EE\u6807\u5E73\u53F0\u57FA\u7EBF", expected, theirs);
@@ -10129,11 +10320,11 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10129
10320
  }
10130
10321
  if (targetChanged && path2.endsWith("package.json") && base) {
10131
10322
  const merged = mergePackageJson(base, ours, theirs);
10132
- return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10323
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict4(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
10133
10324
  }
10134
10325
  if (!oursChanged && targetChanged && adoptedProjectDelta && base) {
10135
10326
  const merged = await mergeTextFile(base, ours, theirs);
10136
- return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76\u5DF2\u91C7\u7EB3\u9879\u76EE\u589E\u91CF", expected, merged.content) : conflict3(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10327
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76\u5DF2\u91C7\u7EB3\u9879\u76EE\u589E\u91CF", expected, merged.content) : conflict4(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10137
10328
  }
10138
10329
  if (!oursChanged) {
10139
10330
  return readyPlannedFile(path2, ownership, "update", "\u4EC5 Windy \u4FEE\u6539", expected, theirs);
@@ -10146,9 +10337,9 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
10146
10337
  }
10147
10338
  if (base) {
10148
10339
  const merged = await mergeTextFile(base, ours, theirs);
10149
- return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10340
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict4(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
10150
10341
  }
10151
- return conflict3(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
10342
+ return conflict4(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
10152
10343
  }
10153
10344
  function shouldForcePlatformBaseline(input) {
10154
10345
  return input.forcePlatformBaseline && !input.oursChanged && input.base !== undefined && hashContent(input.base) !== input.sourceArtifactHash;
@@ -10169,7 +10360,7 @@ function readyPlannedFile(path2, ownership, action, reason, expectedProjectConte
10169
10360
  function expectationForSnapshot(content) {
10170
10361
  return content ? { kind: "hash", value: hashContent(content) } : { kind: "missing" };
10171
10362
  }
10172
- function conflict3(path2, ownership, reason, expectedProjectContent) {
10363
+ function conflict4(path2, ownership, reason, expectedProjectContent) {
10173
10364
  return {
10174
10365
  path: path2,
10175
10366
  ownership,
@@ -11000,9 +11191,9 @@ function assertEnabledConflicts(target, catalog) {
11000
11191
  for (const [name, enabled] of target) {
11001
11192
  if (!enabled)
11002
11193
  continue;
11003
- const conflict4 = catalog.get(name).conflicts.find((candidate) => target.get(candidate));
11004
- if (conflict4)
11005
- throw new Error(`\u6A21\u5757\u51B2\u7A81\uFF1A${name} \u4E0E ${conflict4}`);
11194
+ const conflict5 = catalog.get(name).conflicts.find((candidate) => target.get(candidate));
11195
+ if (conflict5)
11196
+ throw new Error(`\u6A21\u5757\u51B2\u7A81\uFF1A${name} \u4E0E ${conflict5}`);
11006
11197
  }
11007
11198
  }
11008
11199
  function assertCompatible(version, range, name) {
@@ -11017,7 +11208,7 @@ function reconcileProjectModuleRegistryPlan(plan, current, lifecycle) {
11017
11208
  if (!registryFile) {
11018
11209
  throw new Error("\u6A21\u5757\u751F\u547D\u5468\u671F\u8BA1\u5212\u7F3A\u5C11 project-owned \u88C5\u914D\u9009\u62E9");
11019
11210
  }
11020
- plan.conflicts = plan.conflicts.filter((conflict4) => !conflict4.startsWith(`${projectModuleRegistryPath}\uFF1A`));
11211
+ plan.conflicts = plan.conflicts.filter((conflict5) => !conflict5.startsWith(`${projectModuleRegistryPath}\uFF1A`));
11021
11212
  delete registryFile.conflict;
11022
11213
  if (lifecycle.action === "update") {
11023
11214
  registryFile.action = "preserve";
@@ -11447,8 +11638,8 @@ function printModulePlan(plan, log) {
11447
11638
  for (const file of changed) {
11448
11639
  log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
11449
11640
  }
11450
- for (const conflict4 of plan.conflicts)
11451
- log(` conflict ${conflict4}`);
11641
+ for (const conflict5 of plan.conflicts)
11642
+ log(` conflict ${conflict5}`);
11452
11643
  }
11453
11644
  function hasChanges(lifecycle) {
11454
11645
  return lifecycle.addedModules.length > 0 || lifecycle.updatedModules.length > 0 || lifecycle.removedModules.length > 0;
@@ -11620,8 +11811,8 @@ function printPlan(plan) {
11620
11811
  console.log(`\u8BA1\u5212\u6539\u52A8\uFF1A${changed.length} \u4E2A\u6587\u4EF6\uFF1B\u51B2\u7A81\uFF1A${plan.conflicts.length}`);
11621
11812
  for (const file of changed)
11622
11813
  console.log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
11623
- for (const conflict4 of plan.conflicts)
11624
- console.log(` conflict ${conflict4}`);
11814
+ for (const conflict5 of plan.conflicts)
11815
+ console.log(` conflict ${conflict5}`);
11625
11816
  for (const finding of plan.manualCleanup ?? []) {
11626
11817
  console.log(` manual ${finding.message}`);
11627
11818
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-windy",
3
- "version": "0.6.14",
3
+ "version": "0.6.15",
4
4
  "description": "创建单组织、单租户、私有部署优先的 Windy 企业 Dashboard Starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -44,8 +44,8 @@ description: "在 Windy 或 create-windy 生成项目中新增或修改业务 Mo
44
44
  - 流式写入和大报告分别使用可选 Storage Writer / Report Staging Port、显式 policy
45
45
  与 `require*()` helper;Tool 不继承 Writer,缺少 `system.storage` 时直接说明物理
46
46
  裁剪边界。
47
- **完成标准:业务代码未注入 UploadRepository、BlobStore、Secret locator 或平台
48
- manage Repository,缺失 Port 会稳定 fail closed。**
47
+ **完成标准:业务代码未注入 UploadRepository、BlobStore、Secret locator 或平台
48
+ manage Repository,缺失 Port 会稳定 fail closed。**
49
49
  7. 业务资源含敏感字段时,在 Manifest 声明 Data Policy、standard read、
50
50
  sensitive-disclosure reveal、governed-export Permission 和对应 API,再用
51
51
  `registerGovernedResources()` 注册对象授权、脱敏投影、受控字段读取与分页 Source。
@@ -67,17 +67,66 @@ description: "在 Windy 或 create-windy 生成项目中新增或修改业务 Mo
67
67
  和可选 readiness pin。`system.agent` 的面向用户回答使用平台 Supervisor typed
68
68
  final-answer 契约;Durable Handler 只通过 Actor-aware 后台 AI Port 恢复同一幂等
69
69
  Run。浏览器或桌面宿主本地编排模型循环时使用 governed Client Agent Session,不向
70
- 客户端下发 Provider Secret 或 execution grant。**完成标准:Operation 的声明、
71
- Handler、发布坐标、输出投影和运行边界一致。**
70
+ 客户端下发 Provider Secret 或 execution grant。Workflow 需要 PageAgent 产物时复用固定
71
+ `system.agent-workflow.client-agent-artifact` Job taskKey,并在 project-owned Composition
72
+ 登记唯一 Workflow/Node/Operation/Artifact binding;业务 Handler 不直接取得 Client Agent
73
+ Session、Host Auth、BlobStore 或内部 Durable Context Port。Workflow 专用 Operation 声明
74
+ `launchAuthority="workflow-artifact"`;binding 登记 scope contract、project launch、
75
+ client task 与 terminal authority 的静态 version/digest。受保护 Workflow 只能走未暴露为
76
+ 通用路由的 `agentWorkflowProjects` Seam;通用 release/run 即使 digest 相同也 fail closed。
77
+ claim 的 raw input Artifact 只在 Host 当前重授权后交给 client task authority,Web/Extension
78
+ 只消费 ai-client 严格解析后的有界 canonical task,不自行拼 ArtifactRef、locator 或 prompt。
79
+ 模块把 Storage/JSON 作为下游 Workflow input 时,Route 先经两阶段
80
+ `workflowInputMaterialization.begin/resolve` 等待真实 Job succeeded,Handler 再用
81
+ `workflowInputArtifacts` 正式发布,不得把 fileId 当 artifactId;固定 Manifest task 只注册
82
+ 同 key/feature/permission/audit 的 Durable Handler,不额外注册 scheduled no-op。
83
+ **完成标准:Operation 的声明、
84
+ Handler、固定 taskKey、项目绑定、发布坐标、输出投影和运行边界一致。**
72
85
  11. 补齐 Manifest/Composition、Repository/Service、Guard 拒绝和 Handler 契约覆盖;按
73
86
  条件覆盖 Durable 重试/恢复、Tool 未授权发现/调用、资源文件、Secret、治理导出、
74
- 可选模块裁剪、Sandbox 隔离和 AI 恢复。**完成标准:每个新增能力至少有成功路径、
75
- 关键拒绝路径和声明/实现漂移检查。**
87
+ 可选模块裁剪、Sandbox 隔离和 AI 恢复。Client Agent Workflow 还要覆盖 pending/fence
88
+ 原子提交、短期 claim、稳定 receipt/Blob putOnce/Durable publishArtifactOnce、两阶段取消与
89
+ 重启恢复。**完成标准:每个新增能力至少有成功路径、关键拒绝路径和声明/实现漂移检查。**
76
90
  12. 更新长期文档,并按当前仓库 `AGENTS.md` 与 `package.json` 分层验证。windy-platform
77
91
  普通小提交只运行允许的静态检查;合并候选统一运行 `test:merge`,冻结发版候选才运行
78
92
  一次 `release:verify`。仅当项目提供 `lint` 脚本时运行 lint;一个 cohesive slice 一个
79
93
  Conventional Commit。**完成标准:验证层级、未执行项和提交 SHA 均可审计。**
80
94
 
95
+ ## Client Agent Workflow 重复故障解法
96
+
97
+ - 跨层 opaque ID 必须选一个 canonical prefix,并同步 Server 生成器、public SDK、客户端
98
+ validator、样例与文档;不要用“兼容多个前缀”隐藏漂移。
99
+ - 新增 Drizzle Migration 必须同步 SQL、schema、journal 和 snapshot;snapshot `prevId` 精确指向
100
+ 前一 snapshot `id`,并用仓库锁定版本独立再生成比对。
101
+ - Workflow fence 必须约束每一次 Provider attempt:预留前、出网紧前和在途期间从 canonical
102
+ Run/Node/command/generation/fence 与当前授权复核;撤销或 checker 不确定时先 revoke Session。
103
+ - Session finalize 到 Blob/bridge complete 是明确崩溃窗;恢复只读 completed Session 的 receipt、
104
+ final result 和 terminal digest,确定性 `putOnce`/complete,禁止等待浏览器或重放 Provider。
105
+ - completed replay 必须持久化并比较 `receiptIds + result` 的 canonical terminal request digest;
106
+ 完全一致才幂等,任何漂移 fail closed。
107
+ - completed replay 使用 terminal-safe authorization:继续复核当前 Actor/RBAC/Scope、claim/Host/
108
+ Session 与原 Release/Definition/command 不可变坐标,但不能重新要求 command 为 dispatched 或
109
+ Run active;撤权隐藏、摘要漂移冲突。
110
+ - Workflow PageAgent project binding 必须 pin 审核 Release 的 `releaseDigest`;loader 验证固定
111
+ taskKey Job 唯一,且只有无 branch/fallback/skip 的 `job -> artifact -> final` 直接链,Artifact
112
+ kind/policy 与绑定一致。新 Release 必须重新审核,不能静默继承旧权限。
113
+ - 不要用当前 scope digest 等于冻结 Run digest 作为多案授权证明。Host 读取持久 Job scope,验证
114
+ 当前 canonical Actor scope 包含冻结范围;只允许当前更宽或相等,不恢复冻结范围以外权限。
115
+ - terminal authority 的 binding digest 只包含稳定 version/digest,不包含函数;拒绝发生在 Session
116
+ completed transition 前;它必须收到 terminal-time 重新授权并打开的 canonical JSON input artifacts,
117
+ 不能只看 output schema。普通 Run/Session create 必须同时拒绝 workflow-only Operation。
118
+ - project launch authority 必须接收 Host capture 的 `currentAuthorizationScope`,只返回它的收窄范围;
119
+ Host 再做 containment。业务代码不得硬编码或猜 tenant、roleIds、grants。
120
+ - pre-start Workflow input 物化必须是两阶段:Request Context coordinator `begin` 提交固定模块
121
+ materializer 的真实 Durable Job,`resolve` 仅在 succeeded 且 publication/source metadata 完全匹配
122
+ 时返回 refs;begin、Durable payload 与 worker publication 共用 strict parser,mode 字段互斥且拒绝
123
+ unknown/unsafe/超预算 JSON。ready 后业务 prepare 仍重读 sourceIds 并逐项匹配,Workflow start
124
+ 再复验 Artifact。
125
+ - Targeted patch 新增 project-owned seam 时,连续 recipe 必须覆盖 public source 缺失、精确旧默认空、
126
+ 精确新默认空和客户修改四态。binding 用完整字节白名单;Composition 的 import/type/runtime property
127
+ 作为原子唯一锚点组。任何部分装配、重复、换行/注释漂移或非空客户 binding 都在写入前 fail closed;
128
+ 未选择所属可选模块时不得注入 seam。candidate regression 固定以上一公开版本为直接来源。
129
+
81
130
  ## 项目所有权与自动装配
82
131
 
83
132
  - `apps/web/src`、`apps/server/src/app`、业务模块源码和 `windy.modules.json` 都是
@@ -98,7 +147,8 @@ description: "在 Windy 或 create-windy 生成项目中新增或修改业务 Mo
98
147
  `packages/server-sdk/src/request-context.ts`、`packages/server-sdk/src/durable-handler.ts`
99
148
  - Tool 与 AI:`packages/server-sdk/src/tool-registration.ts`、
100
149
  `packages/server-sdk/src/sandbox-tool.ts`、
101
- `packages/server-sdk/src/ai-operation-registration.ts`
150
+ `packages/server-sdk/src/ai-operation-registration.ts`、
151
+ `packages/server-sdk/src/client-agent-workflow-artifact.ts`
102
152
  - Secret、Storage 与治理:`packages/server-sdk/src/secret-port.ts`、
103
153
  `packages/server-sdk/src/secret-binding.ts`、`packages/server-sdk/src/storage-port.ts`、
104
154
  `packages/server-sdk/src/report-staging-port.ts`、
@@ -111,7 +161,7 @@ description: "在 Windy 或 create-windy 生成项目中新增或修改业务 Mo
111
161
  - 条件能力:`docs/architecture/module-secret-resolution.md`、
112
162
  `docs/architecture/report-staging.md`、`docs/platform/governed-export-renderers.md`、
113
163
  `docs/platform/agent-tool-approval.md`、`docs/platform/background-ai-operations.md`、
114
- `docs/platform/client-agent-session.md`
164
+ `docs/platform/client-agent-session.md`、`docs/architecture/agent-workflow.md`
115
165
 
116
166
  某个事实源或 `system.agent` / `system.storage` 不存在时,先说明当前生成组合的物理边界,
117
167
  不在业务层补一套替代实现。
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "templateCommit": "74fc88e548934dbda773291c4ad078d16a5396d1",
4
- "generatorVersion": "0.6.14",
3
+ "templateCommit": "270df5f3da5ba6512a0f305109d874f2c8bf757e",
4
+ "generatorVersion": "0.6.15",
5
5
  "modules": [
6
6
  {
7
7
  "name": "system",