cabloy 5.1.125 → 5.1.126

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 (104) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +1 -1
  3. package/.claude/skills/cabloy-backend-scaffold/evals/evals.json +6 -0
  4. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +13 -4
  5. package/.claude/skills/cabloy-workflow/SKILL.md +4 -2
  6. package/.claude/skills/cabloy-workflow/evals/evals.json +14 -2
  7. package/.claude/skills/cabloy-worktree-environment/SKILL.md +206 -0
  8. package/.claude/skills/cabloy-worktree-environment/evals/evals.json +77 -0
  9. package/.github/workflows/vona-test-pg.yml +3 -0
  10. package/.github/workflows/vona-test-sqlite3.yml +3 -0
  11. package/CHANGELOG.md +15 -0
  12. package/CLAUDE.md +1 -1
  13. package/cabloy-docs/.vitepress/config.mjs +1 -0
  14. package/cabloy-docs/backend/backend-contract-emission-specimen.md +2 -2
  15. package/cabloy-docs/backend/dto-guide.md +10 -7
  16. package/cabloy-docs/backend/dto-infer-generation.md +127 -7
  17. package/cabloy-docs/backend/foundation.md +1 -1
  18. package/cabloy-docs/backend/introduction.md +1 -0
  19. package/cabloy-docs/backend/module-dependencies.md +104 -0
  20. package/cabloy-docs/backend/serialization-guide.md +6 -0
  21. package/cabloy-docs/fullstack/parallel-worktree-environment.md +72 -34
  22. package/cabloy-docs/fullstack/suites-and-modules.md +1 -0
  23. package/cabloy-docs/reference/package-map.md +1 -0
  24. package/e2e/specs/a-commerce/commerce.spec.ts +89 -0
  25. package/package.json +2 -1
  26. package/scripts/init.ts +7 -12
  27. package/scripts/initAppName.test.ts +72 -0
  28. package/scripts/initAppName.ts +50 -0
  29. package/vona/packages-vona/vona/package.json +1 -1
  30. package/vona/pnpm-lock.yaml +27 -147
  31. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineCreate.tsx +6 -27
  32. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineItem.tsx +6 -31
  33. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineUpdate.tsx +6 -2
  34. package/vona/src/suite/a-commerce/modules/commerce-member/src/lib/addressMine.ts +16 -0
  35. package/vona/src/suite/a-commerce/modules/commerce-member/src/service/address.ts +4 -17
  36. package/vona/src/suite/a-commerce/modules/commerce-member/test/addressOwnership.test.ts +63 -19
  37. package/vona/src/suite/a-commerce/modules/commerce-payment/package.json +2 -1
  38. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/payScene.commerceOrder.ts +11 -2
  39. package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/commercePayScene.ts +26 -0
  40. package/vona/src/suite/a-commerce/modules/commerce-payment/test/paymentAttempt.test.ts +19 -2
  41. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/en-us.ts +5 -2
  42. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/zh-cn.ts +5 -2
  43. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateCreate.tsx +26 -35
  44. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateUpdate.tsx +6 -1
  45. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/entity/couponTemplate.tsx +40 -4
  46. package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponTemplateFormLayout.test.ts +85 -0
  47. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +1 -1
  48. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/order.ts +3 -5
  49. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSummary.tsx +7 -40
  50. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/shipmentView.tsx +6 -15
  51. package/vona/src/suite/a-commerce/modules/commerce-trade/src/lib/order.ts +9 -0
  52. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +121 -11
  53. package/vona/src/suite/a-commerce/modules/commerce-trade/test/order.test.ts +25 -0
  54. package/vona/src/suite/a-commerce/modules/commerce-trade/test/paymentOutcome.test.ts +19 -2
  55. package/vona/src/suite/a-training/modules/training-record/src/dto/detailRecordSubjectResItem.tsx +6 -1
  56. package/vona/src/suite/a-training/modules/training-record/src/dto/recordSelectResItem.tsx +3 -1
  57. package/vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx +4 -1
  58. package/vona/src/suite/a-training/modules/training-record/test/record.test.ts +45 -0
  59. package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordResItem.tsx +6 -1
  60. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +5 -23
  61. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +37 -5
  62. package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
  63. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +29 -0
  64. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.index.ts +3 -0
  65. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.redlock.ts +3 -1
  66. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.version.ts +7 -0
  67. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/queue.outboxDispatch.ts +9 -4
  68. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/schedule.providerOperationDispatch.ts +11 -0
  69. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/outboxEvent.tsx +11 -4
  70. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/providerOperation.tsx +12 -0
  71. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/webhookInbox.tsx +6 -0
  72. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/outbox.ts +12 -5
  73. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentSession.ts +1 -37
  74. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/providerOperation.ts +355 -1
  75. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/refundOperation.ts +226 -0
  76. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/webhook.ts +148 -50
  77. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payScene.ts +2 -1
  78. package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
  79. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +39 -22
  80. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/bean/payProvider.mock.ts +42 -13
  81. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/controller/mockPayment.ts +11 -0
  82. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockRefundComplete.tsx +13 -0
  83. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockRefundReceipt.tsx +16 -0
  84. package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/service/payMock.ts +56 -0
  85. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +2 -1
  86. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/bean/payProvider.paypal.ts +117 -8
  87. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +1 -1
  88. package/vona/src/suite-vendor/a-pay/package.json +5 -5
  89. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  90. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGet.ts +5 -5
  91. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  92. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +54 -12
  93. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +625 -64
  94. package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/types.ts +55 -15
  95. package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +1 -1
  96. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeOrder.ts +15 -17
  97. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +12 -8
  98. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +111 -26
  99. package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeOrder.ts +3 -3
  100. package/zova/src/suite/a-commerce/modules/commerce-trade/src/component/tableCellActionRefund/controller.tsx +1 -8
  101. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +5 -9
  102. package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +1 -1
  103. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +301 -17
  104. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +5461 -1788
package/.cabloy-version CHANGED
@@ -1 +1 @@
1
- 5.1.125
1
+ 5.1.126
@@ -168,7 +168,7 @@ Then distinguish runtime lookup from a true module dependency:
168
168
  - do not add a dependency declaration merely because code looks up another module's service, model, config, locale, or other resource
169
169
  - scope lookup cannot make an absent module available; validate application/suite composition separately when the target must exist
170
170
 
171
- For the canonical distinction, read [Backend Foundation](../../../cabloy-docs/backend/foundation.md#scope-lookup-vs-module-dependencies) and [Package Map](../../../cabloy-docs/reference/package-map.md).
171
+ For the canonical decision guide, read [Vona Module Dependencies](../../../cabloy-docs/backend/module-dependencies.md), with [Backend Foundation](../../../cabloy-docs/backend/foundation.md#scope-lookup-vs-module-dependencies) and [Package Map](../../../cabloy-docs/reference/package-map.md) as companions.
172
172
 
173
173
  ### Verification
174
174
 
@@ -24,6 +24,12 @@
24
24
  "prompt": "I changed a model relation and some entity fields in Cabloy Basic. Before you tell me anything else, I want the Cabloy backend done-checklist, not a broad explanation of ORM theory.",
25
25
  "expected_output": "Must give a concrete backend completion checklist, must include relation-aware follow-up and metadata or migration review, and must stay practical rather than drifting into generic ORM explanation.",
26
26
  "files": []
27
+ },
28
+ {
29
+ "id": 15,
30
+ "prompt": "My Vona service reads another module through this.$scope. Should I add vonaModule.dependencies? In a separate feature, my monkey.ts must extend a target module during startup. Explain the decision for both cases.",
31
+ "expected_output": "Must distinguish scope lookup from a module dependency edge, state that lookup alone does not require vonaModule.dependencies, and identify required availability, dependency-first ordering, or minimum compatible version as the criteria. Must recognize startup or monkey integration as a possible ordering case, verify composition separately, and reject speculative or circular edges.",
32
+ "files": []
27
33
  }
28
34
  ]
29
35
  }
@@ -14,6 +14,12 @@ After generating or extending a backend thread, check which follow-up layers app
14
14
  - validation rules
15
15
  - OpenAPI metadata
16
16
  - inferred DTO opportunities
17
+ - treat `$Dto.get(...)` as the complete model-aware read shape by default; use `columns` or `dtoClass` only for a genuine business/query/response projection, not solely to remove `iid` or `deleted`
18
+ - treat the top-level `$Dto.create(...)` / `$Dto.update(...)` default omissions as a write-input authorization boundary, not as a reason to mechanically narrow ordinary `$Dto.get(...)` contracts
19
+ - when a narrowed DTO or OpenAPI schema is expected to remove physical response fields, separately shape and verify the action response; declaration narrowing alone does not guarantee runtime field stripping
20
+ - when stable Entity, Model, relation, or query truth exists, define the DTO projection first with `$Dto.*` and, where needed, `columns`, `include`, or `dtoClass`
21
+ - for an inferred field, use `$makeMetadata(...)` for metadata-only refinement and `$makeSchema(...)` for schema or validation refinement; use a class-body `@Api.field(...)` member only for a genuinely new field
22
+ - when inference cannot express the contract clearly, choose an explicit DTO deliberately; see [Default-first three-layer DTO authoring](../../../../cabloy-docs/backend/dto-infer-generation.md#default-first-three-layer-dto-authoring)
17
23
  - frontend contract impact
18
24
  - `@Api.field(...)` / `$makeSchema(...)` ordering: framework guards now preserve previously attached OpenAPI metadata across schema rebuilds, but structure-shaping schemaLike is still order-sensitive
19
25
  - when an explicit zod/custom schema or other structure-defining schemaLike is present, put that structure-defining schemaLike last because `makeSchemaLikes(...)` applies arguments right-to-left and later structure changes can otherwise alter or replace the intended schema
@@ -50,10 +56,13 @@ After generating or extending a backend thread, check which follow-up layers app
50
56
 
51
57
  ## Module composition and dependency intent
52
58
 
53
- - target module is already composed into the application when code uses cross-module scope lookup
54
- - cross-module `this.$scope.<module>` or `app.scope(...)` lookup alone does not require `vonaModule.dependencies`
55
- - `vonaModule.dependencies` is added only for a genuine target-module availability, dependency-first ordering, or minimum-version requirement
56
- - do not create speculative dependency edges or circular declarations merely to document a lookup
59
+ - confirm package, suite, or application composition already supplies a target before using cross-module lookup; lookup cannot compose an absent module
60
+ - choose the narrowest lookup form first: `this.scope` for local resources, `this.$scope.<module>` for a fixed cross-module target, and `app.scope(...)` when an application reference or genuinely dynamic target is required
61
+ - cross-module scope lookup, a named ORM relation, or `$Dto.get(..., { include })` alone does not require `vonaModule.dependencies`
62
+ - add `vonaModule.dependencies` only for a genuine target-module availability, dependency-first ordering, or minimum-version requirement
63
+ - startup, lifecycle, or `monkey.ts` integration can require dependency-first ordering, but are not the only valid dependency case
64
+ - when adding an edge, verify package/suite composition, the target relative module name, the minimum compatible version, and that the graph remains acyclic
65
+ - do not create speculative dependency edges or circular declarations merely to document a lookup; read [Vona Module Dependencies](../../../../cabloy-docs/backend/module-dependencies.md) for the canonical decision guide
57
66
 
58
67
  ## Verification follow-up
59
68
 
@@ -100,9 +100,11 @@ The reason is simple: these files are where Cabloy already encodes its real work
100
100
 
101
101
  ### Parallel worktree environment setup
102
102
 
103
- When a request involves a second worktree, concurrent Vona/Zova development, isolated ordinary tests, or managed clean E2E, classify it as fullstack workflow setup. Read [Parallel Worktree Environment](../../../cabloy-docs/fullstack/parallel-worktree-environment.md) for the canonical Cabloy Basic recipe.
103
+ When a request involves a second worktree, concurrent Vona/Zova development, isolated ordinary tests, or managed clean E2E, classify it as fullstack workflow setup. Read [Parallel Worktree Environment](../../../cabloy-docs/fullstack/parallel-worktree-environment.md), the canonical shared recipe maintained in Cabloy Basic for both editions.
104
104
 
105
- Before applying the broad `.env.local` recipe, check for more-specific `.env.*.local` overrides. Keep Vona and Zova `APP_NAME` values aligned, use the required matching API target, and add database, Redis, external-service, mock, or SSR-preview isolation only when the work actually uses those shared resources. For Cabloy Start, inspect the active Start repository rather than reusing the Basic recipe unchanged.
105
+ This routing skill provides read-only guidance only. Do not infer an `APP_NAME` or ports, edit local overrides, or run `npm run init` from a generic worktree request. When the user wants confirmation-gated local environment setup, ask them to explicitly invoke `/cabloy-worktree-environment`.
106
+
107
+ The invoked skill detects Basic or Start to select the active root scripts and managed clean-E2E command. It uses Git worktree metadata, fixed Vona/Zova port baselines, and the worktree basename to recommend the complete standard tuple for confirmation: `APP_NAME`, `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, `DEV_SERVER_HMR_PORT`, and an `API_BASE_URL` derived from the Vona port. After confirmation, it writes both `vona/env/.env.local` and `zova/env/.env.local`; never use flavor-, mode-, app-mode-, or runtime-specific `.env.*.local` files. It does not inspect environment-file content or allocate/reserve a live port. The shared environment is Vona + Zova development: Admin and Web are alternative commands using the same configuration, and they must not run concurrently in one worktree. Concurrent use requires separately configured linked worktrees.
106
108
 
107
109
  ## Step 4: Prefer CLI-first workflows
108
110
 
@@ -33,8 +33,20 @@
33
33
  },
34
34
  {
35
35
  "id": 6,
36
- "prompt": "I created a second Cabloy Basic worktree and need to run Vona, Zova, and test:e2e:basic:clean in parallel with the first worktree. Which environment files and exact variables should I configure without changing shared defaults?",
37
- "expected_output": "Classifies this as fullstack parallel-worktree environment setup and routes to the canonical Parallel Worktree Environment guide. Checks for more-specific local overrides, uses Vona vona/env/.env.local with APP_NAME and SERVER_LISTEN_PORT, and Zova zova/env/.env.local with the same APP_NAME plus API_BASE_URL pointing to that Vona port, DEV_SERVER_PORT, and DEV_SERVER_HMR_PORT. Keeps SSR_API_BASE_URL inherited from API_BASE_URL unless a more-specific override changes it, and adds database, Redis, external-service, mock, or SSR-preview settings only when those resources are actually used.",
36
+ "prompt": "I created a second Cabloy Basic worktree and need to run Vona, Zova Admin, and test:e2e:basic:clean in parallel with the first worktree. Which environment files and exact variables should I configure without changing shared defaults?",
37
+ "expected_output": "Classifies this as fullstack parallel-worktree environment setup and routes to the canonical shared Parallel Worktree Environment guide. Explains that generic routing is read-only: it must not inspect env content, infer or write local values, or run npm run init. Directs the user to explicitly invoke /cabloy-worktree-environment for confirmation-gated setup. The invoked skill uses Git worktree metadata, the worktree basename, and fixed baseline ports to recommend APP_NAME, SERVER_LISTEN_PORT, DEV_SERVER_PORT, DEV_SERVER_HMR_PORT, and a derived API_BASE_URL, then writes only vona/env/.env.local and zova/env/.env.local after confirmation. It does not use a flavor-specific local file or reserve ports; Admin and Web are alternative non-concurrent commands using the shared tuple.",
38
+ "files": []
39
+ },
40
+ {
41
+ "id": 7,
42
+ "prompt": "I created a linked Cabloy Start worktree and need isolated Vona, Zova Web, and managed clean E2E. Which workflow should I use?",
43
+ "expected_output": "Routes to the canonical shared guide and explicitly invoked /cabloy-worktree-environment skill. It recognizes that the invoked skill selects the Start command npm run test:e2e:start:clean while retaining read-only generic routing, a deterministic Git-metadata recommendation, no environment-content inspection, no automatic initialization, and the universal five-setting tuple written to both permitted broad local files only after confirmation.",
44
+ "files": []
45
+ },
46
+ {
47
+ "id": 8,
48
+ "prompt": "I created a linked Cabloy Basic worktree and only need backend tests. What should I do for local environment isolation?",
49
+ "expected_output": "Keeps generic routing read-only and directs the user to the canonical guide plus explicit /cabloy-worktree-environment invocation. It explains that the invoked skill still generates the universal APP_NAME, SERVER_LISTEN_PORT, DEV_SERVER_PORT, DEV_SERVER_HMR_PORT, and derived API_BASE_URL tuple in both broad local files after confirmation; it does not provide a backend-only one-file path.",
38
50
  "files": []
39
51
  }
40
52
  ]
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: cabloy-worktree-environment
3
+ description: This skill must be used only when the user explicitly invokes /cabloy-worktree-environment or explicitly asks to perform the named Cabloy worktree-environment setup. It prepares a confirmation-gated, worktree-local Vona and Zova runtime environment for a linked Cabloy Basic or Cabloy Start Git worktree using Git metadata and fixed port baselines only. Do not use it merely because a request mentions worktrees, parallel work, ports, development, tests, or E2E; route those requests to cabloy-workflow for read-only guidance instead.
4
+ ---
5
+
6
+ # Cabloy Worktree Environment
7
+
8
+ Use this skill only for explicit, user-controlled setup of the standard local runtime environment in an already-created linked Git worktree.
9
+
10
+ ## Goals
11
+
12
+ 1. validate that the current checkout is a linked Cabloy Basic or Cabloy Start worktree before any write
13
+ 2. generate a deterministic, secret-safe core environment tuple from Git worktree metadata and fixed port baselines
14
+ 3. never read, parse, source, expand, display, log, or send `.env*` file contents to the model
15
+ 4. write only a new or empty `vona/env/.env.local` and `zova/env/.env.local` in the current worktree after explicit confirmation
16
+ 5. keep Admin and Web as alternative runtime commands that share one generated Zova configuration
17
+ 6. keep `npm run init` a separate, opt-in decision
18
+
19
+ ## Step 1: Validate the current checkout and edition
20
+
21
+ Before proposing configuration values or writing files:
22
+
23
+ 1. resolve the current absolute Git top-level directory
24
+ 2. run `git worktree list --porcelain -z` and parse its NUL-delimited records without shell word splitting
25
+ 3. verify that the current root is registered
26
+ 4. compare absolute `git-dir` and `git-common-dir`; equal paths identify the primary checkout, which this skill must reject
27
+ 5. detect exactly one edition marker at the resolved root
28
+ 6. verify that `vona/env/`, `zova/env/`, and the required root scripts exist
29
+
30
+ Interpretation:
31
+
32
+ | Marker | Edition | Managed clean E2E command |
33
+ | --- | --- | --- |
34
+ | `__CABLOY_BASIC__` only | Cabloy Basic | `npm run test:e2e:basic:clean` |
35
+ | `__CABLOY_START__` only | Cabloy Start | `npm run test:e2e:start:clean` |
36
+
37
+ Stop without edits when both markers are present, neither marker is present, the checkout is primary/unregistered, required environment directories are missing, or the selected edition's required scripts are unavailable.
38
+
39
+ Read [Parallel Worktree Environment](../../../cabloy-docs/fullstack/parallel-worktree-environment.md) as the canonical shared recipe. Edition detection chooses command names and labels; it does not change the two-file environment model. Never change committed defaults, including `vona/env/.env` and `zova/env/.env`.
40
+
41
+ ## Step 2: Generate the standard environment recommendation
42
+
43
+ After validation, immediately generate the standard core tuple. Do not ask which processes the user intends to run and do not ask them to select Admin or Web.
44
+
45
+ For user-facing summaries, write exactly:
46
+
47
+ > 环境隔离信息:Vona 开发 + Zova 开发
48
+
49
+ Admin and Web use this same Zova environment. The user may later run either frontend command, but must not run both concurrently in one worktree. Use another linked worktree for concurrent development of the other flavor. Do not create a flavor-specific local override.
50
+
51
+ ### Secret-safe input boundary
52
+
53
+ Recommendation generation uses Git worktree metadata and the fixed constants below only. It must not inspect any `.env`, `.env.local`, `.env.*.local`, sibling worktree configuration, process environment, listener table, `lsof` output, process command line, or external service. Do not use `Read`, `cat`, `grep`, `source`, `dotenv`, `printenv`, `env`, or diagnostics that expose env-file content for this workflow.
54
+
55
+ This means the proposal is deterministic convenience, not a live port reservation. If an application later reports a port collision, the user may say **“再换一批”** before setup or create another linked worktree; the actual application bind remains authoritative.
56
+
57
+ ### Deterministic proposal
58
+
59
+ Treat the primary checkout as ordinal `0`. From the validated `git worktree list --porcelain -z` order, assign each linked worktree the next ordinal: the first linked worktree is `1`, the second is `2`, and so on. Let `batch` be `0` for the first proposal, and increase it only when the user says **“再换一批”**.
60
+
61
+ Use one shared offset for every generated listener:
62
+
63
+ ```text
64
+ offset = linkedWorktreeOrdinal + batch
65
+ ```
66
+
67
+ Use these fixed baseline ports, which match the committed Cabloy defaults:
68
+
69
+ | Setting | Baseline | Recommended value |
70
+ | --- | ---: | --- |
71
+ | `SERVER_LISTEN_PORT` | `7102` | `7102 + offset` |
72
+ | `DEV_SERVER_PORT` | `9000` | `9000 + offset` |
73
+ | `DEV_SERVER_HMR_PORT` | `24679` | `24679 + offset` |
74
+
75
+ Set `APP_NAME` to the basename of the validated current worktree root. Do not inspect other worktrees’ configurations or append an env-derived suffix. Stop if that basename is empty or cannot be used as an application name without altering it; ask the user to rename/recreate the linked worktree instead.
76
+
77
+ Always recommend both local files:
78
+
79
+ ```dotenv
80
+ # vona/env/.env.local
81
+ APP_NAME = <worktree-basename>
82
+ SERVER_LISTEN_PORT = <7102 + offset>
83
+ ```
84
+
85
+ ```dotenv
86
+ # zova/env/.env.local
87
+ APP_NAME = <worktree-basename>
88
+ API_BASE_URL = http://localhost:<recommended SERVER_LISTEN_PORT>
89
+ DEV_SERVER_PORT = <9000 + offset>
90
+ DEV_SERVER_HMR_PORT = <24679 + offset>
91
+ ```
92
+
93
+ All generated listener ports must be integers from `1` through `65535` and distinct within the tuple. If a batch would exceed that range, stop and require a different linked-worktree arrangement.
94
+
95
+ When the user says **“再换一批”**, set `batch = batch + 1`, recompute the entire tuple, and show it again. Every recommended listener advances by exactly `+1`, and `API_BASE_URL` is regenerated from the new Vona port. Do not write during a batch change. This deterministic setup does not accept user-substituted values.
96
+
97
+ A unique `APP_NAME` separates ordinary framework-managed test database names and framework Redis prefixes. It does not isolate explicitly named databases, unprefixed custom Redis keys, mail, payment, webhooks, object storage, or other external services. Require a separate explicit design before claiming that any of those resources are isolated.
98
+
99
+ ## Step 3: Preview and confirm the write
100
+
101
+ Before making any edit:
102
+
103
+ 1. show `环境隔离信息:Vona 开发 + Zova 开发`, the worktree ordinal, batch, and exact non-secret identity/port tuple
104
+ 2. show a file-by-file preview containing only the managed assignments that will be written to both broad local files
105
+ 3. run one independent `git check-ignore -v -- "$target"` command for each target and require each command to succeed with a matching ignore rule
106
+ 4. recheck current root, linked-worktree identity, edition, ordinal, generated port range, tuple uniqueness, and both target states
107
+ 5. ask for a final affirmative confirmation that includes the proposed identity and port tuple
108
+
109
+ Do not treat silence as confirmation.
110
+
111
+ ## Step 4: Apply only safe broad local overrides
112
+
113
+ The only files this skill may create or change are:
114
+
115
+ - `vona/env/.env.local`
116
+ - `zova/env/.env.local`
117
+
118
+ To preserve the no-env-content-disclosure boundary, inspect only each target's existence and whether it is empty; do not read its contents. If either target already exists and is non-empty, stop without reading or modifying either file. Explain that this skill deliberately will not access a pre-existing local environment file because it may contain secrets; the user must manage it outside this workflow or use a fresh linked worktree.
119
+
120
+ Only after final confirmation:
121
+
122
+ 1. immediately re-run one independent `git check-ignore -v -- "$target"` command for each target and abort unless each succeeds with a matching ignore rule
123
+ 2. confirm both targets are absent or empty without reading their content
124
+ 3. snapshot only each target's existence and empty-file state
125
+ 4. write the exact previewed Vona assignments to `vona/env/.env.local`
126
+ 5. write the exact previewed Zova assignments to `zova/env/.env.local`
127
+ 6. do not create, modify, remove, inspect, or recommend flavor-, mode-, app-mode-, or runtime-specific `.env.*.local` files
128
+
129
+ Never:
130
+
131
+ - edit another worktree
132
+ - read, parse, source, expand, display, or log existing environment-file content
133
+ - edit committed `.env` defaults
134
+ - add mock, preview, or other runtime-specific listener settings through this workflow
135
+ - claim that a deterministic recommendation has allocated or reserved a port
136
+ - generate values or write configuration merely to bypass a busy shared resource
137
+
138
+ If a write cannot complete, restore each already changed target to its exact prior state: remove a newly created target or restore an originally empty target to an empty file. Report only the path and operation stage; never include environment-file content in the failure output.
139
+
140
+ ## Step 5: Revalidate and offer initialization separately
141
+
142
+ After writing, verify only the known assignments that this skill generated and wrote, without re-reading any pre-existing local content. Confirm:
143
+
144
+ - the generated Vona and Zova `APP_NAME` values match
145
+ - `API_BASE_URL` targets the generated Vona port
146
+ - `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, and `DEV_SERVER_HMR_PORT` are distinct
147
+ - both target paths and edition commands remain valid
148
+
149
+ Report only the files changed, the generated non-secret tuple, and external resources that remain shared.
150
+
151
+ Then ask exactly:
152
+
153
+ > The local environment overrides are configured. Do you want to run `npm run init` now?
154
+
155
+ Do not run it without an affirmative answer. Explain that `npm run init` is not an environment allocator: it installs dependencies and runs generation/build-related work. In this linked worktree, it preserves the tracked base `APP_NAME` defaults in `vona/env/.env` and `zova/env/.env`; the generated broad `.env.local` files remain the worktree-specific identity source. Primary-checkout and non-Git project initialization may still establish base `APP_NAME` from the project directory.
156
+
157
+ ## Verification
158
+
159
+ Use focused checks appropriate to the detected edition:
160
+
161
+ ```bash
162
+ git worktree list --porcelain -z
163
+ git rev-parse --path-format=absolute --show-toplevel
164
+ git rev-parse --path-format=absolute --git-dir
165
+ git rev-parse --path-format=absolute --git-common-dir
166
+ for target in vona/env/.env.local zova/env/.env.local; do
167
+ git check-ignore -v -- "$target" || exit 1
168
+ done
169
+ ```
170
+
171
+ Run one frontend command, not both:
172
+
173
+ ```bash
174
+ npm run dev
175
+ npm run dev:zova:admin
176
+ # or
177
+ npm run dev:zova:web
178
+ npm run test
179
+ ```
180
+
181
+ Run the edition-appropriate managed clean E2E command:
182
+
183
+ ```bash
184
+ # Cabloy Basic
185
+ npm run test:e2e:basic:clean
186
+
187
+ # Cabloy Start
188
+ npm run test:e2e:start:clean
189
+ ```
190
+
191
+ Finish with a metadata-only status check. Do not use `git diff`, because it can print environment-file content:
192
+
193
+ ```bash
194
+ git status --short
195
+ ```
196
+
197
+ ## Response pattern
198
+
199
+ When this skill completes a stage, report:
200
+
201
+ 1. validated worktree root and detected edition
202
+ 2. `环境隔离信息:Vona 开发 + Zova 开发`
203
+ 3. worktree ordinal, batch, and generated non-secret identity/ports
204
+ 4. both exact broad local files proposed or changed
205
+ 5. the privacy boundary and external resources that still require separate isolation
206
+ 6. the separate `npm run init` question only after successful local setup
@@ -0,0 +1,77 @@
1
+ {
2
+ "skill_name": "cabloy-worktree-environment",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "I explicitly invoke /cabloy-worktree-environment in the first linked Cabloy Basic worktree. Configure the local environment.",
7
+ "expected_output": "Validates that the current checkout is a linked Cabloy Basic worktree before any write. Without asking which processes or frontend flavor will run, it uses Git worktree metadata only and recommends APP_NAME from the worktree basename, SERVER_LISTEN_PORT 7103, DEV_SERVER_PORT 9001, DEV_SERVER_HMR_PORT 24680, and API_BASE_URL http://localhost:7103. It labels the configuration as 环境隔离信息:Vona 开发 + Zova 开发, previews both vona/env/.env.local and zova/env/.env.local, waits for final confirmation before writing, and separately asks whether to run npm run init after success.",
8
+ "files": []
9
+ },
10
+ {
11
+ "id": 2,
12
+ "prompt": "I explicitly invoke /cabloy-worktree-environment in the second linked Cabloy Start worktree. Set up the standard local environment.",
13
+ "expected_output": "Detects __CABLOY_START__, selects npm run test:e2e:start:clean for later verification, and uses the shared canonical workflow. Without a process-selection question, it derives APP_NAME from the worktree basename and, for ordinal 2 batch 0, recommends SERVER_LISTEN_PORT 7104, DEV_SERVER_PORT 9002, DEV_SERVER_HMR_PORT 24681, and API_BASE_URL http://localhost:7104. It uses only the two broad local targets and waits for final confirmation before writing both.",
14
+ "files": []
15
+ },
16
+ {
17
+ "id": 3,
18
+ "prompt": "I explicitly invoke /cabloy-worktree-environment from the primary Cabloy Basic checkout. Set up a second local runtime here so I can avoid the port already in use.",
19
+ "expected_output": "Rejects the request without writing because the current checkout is the primary checkout rather than a linked worktree. It does not modify shared identity or ports merely to bypass a busy resource.",
20
+ "files": []
21
+ },
22
+ {
23
+ "id": 4,
24
+ "prompt": "I explicitly invoke /cabloy-worktree-environment in a linked Cabloy Basic worktree. I only plan to run ordinary backend tests.",
25
+ "expected_output": "Does not ask the user to select processes and still recommends the universal five-setting tuple: worktree-basename APP_NAME, SERVER_LISTEN_PORT, DEV_SERVER_PORT, DEV_SERVER_HMR_PORT, and an API_BASE_URL derived from the server port. After confirmation it writes both vona/env/.env.local and zova/env/.env.local, while explaining that external services require separate isolation decisions.",
26
+ "files": []
27
+ },
28
+ {
29
+ "id": 5,
30
+ "prompt": "I explicitly invoke /cabloy-worktree-environment in a linked Cabloy Basic worktree and later want to use Admin and Web frontend commands.",
31
+ "expected_output": "Generates the same shared standard tuple without asking for a frontend flavor and never proposes a flavor-specific .env.XXX.local file. It explains that Admin and Web use the generated Zova configuration but must not run concurrently in one worktree; another linked worktree is required for concurrent use.",
32
+ "files": []
33
+ },
34
+ {
35
+ "id": 6,
36
+ "prompt": "I explicitly invoke /cabloy-worktree-environment in a linked Cabloy Start worktree and also intend to use SSR preview later.",
37
+ "expected_output": "Generates only the universal five-setting Vona and Zova tuple in the two broad local files. It does not add MOCK_BUILD_PORT, SSR_PROD_PORT, SSR_API_BASE_URL, or another runtime-specific local file; those require a separately designed workflow.",
38
+ "files": []
39
+ },
40
+ {
41
+ "id": 7,
42
+ "prompt": "I explicitly invoke /cabloy-worktree-environment in a linked Cabloy Basic worktree, but zova/env/.env.local is tracked or not ignored.",
43
+ "expected_output": "Runs an independent git check-ignore -v -- target command for both broad targets and rejects the write before confirmation because every target must be ignored. It does not fall back to a specific local file or modify the tracked target.",
44
+ "files": []
45
+ },
46
+ {
47
+ "id": 8,
48
+ "prompt": "I explicitly invoke /cabloy-worktree-environment in the first linked Cabloy Basic worktree. The initial proposal is 7103, 9001, and 24680. 再换一批。",
49
+ "expected_output": "Keeps the same worktree APP_NAME, increases the shared batch by one, and proposes SERVER_LISTEN_PORT 7104, DEV_SERVER_PORT 9002, DEV_SERVER_HMR_PORT 24681, and API_BASE_URL http://localhost:7104. It does not write, inspect ports, inspect environment files, or treat either batch as reserved before final confirmation.",
50
+ "files": []
51
+ },
52
+ {
53
+ "id": 9,
54
+ "prompt": "I explicitly invoke /cabloy-worktree-environment for a linked Cabloy Basic worktree. My local .env.local files may contain credentials. Set up the standard local environment.",
55
+ "expected_output": "Uses only Git worktree metadata, fixed port baselines, and the worktree basename. It does not read, parse, source, expand, print, log, or send any .env* contents, process environment, listener table, or sibling configuration to the model. If either target broad local file exists and is non-empty at the confirmed write stage, it stops without reading or modifying either file.",
56
+ "files": []
57
+ },
58
+ {
59
+ "id": 10,
60
+ "prompt": "I explicitly invoke /cabloy-worktree-environment for a linked Cabloy Basic worktree. Writing zova/env/.env.local fails after vona/env/.env.local was created.",
61
+ "expected_output": "Uses only absent or empty permitted targets, snapshots their existence and empty-file state without reading content, removes every target newly created during the failed operation, restores any originally empty target to empty state, and reports the failure without leaving a partial configuration or exposing environment-file content.",
62
+ "files": []
63
+ },
64
+ {
65
+ "id": 11,
66
+ "prompt": "/cabloy-worktree-environment",
67
+ "expected_output": "After validating that the current checkout is a linked Cabloy worktree, immediately proposes the complete universal tuple and previews both broad local files. It does not ask the user to choose Vona, tests, E2E, Admin, or Web before the final confirmation.",
68
+ "files": []
69
+ },
70
+ {
71
+ "id": 12,
72
+ "prompt": "I confirm the proposed standard tuple in a valid linked worktree.",
73
+ "expected_output": "Rechecks ignore rules and absent-or-empty state for both permitted targets, then writes vona/env/.env.local and zova/env/.env.local together. It validates their generated assignments without reading prior content and only then asks the exact separate npm run init question.",
74
+ "files": []
75
+ }
76
+ ]
77
+ }
@@ -34,6 +34,9 @@ jobs:
34
34
  version: 11.5.2
35
35
  - name: init
36
36
  run: npm run init
37
+ - name: run A-Pay focused gate
38
+ run: DATABASE_DEFAULT_CLIENT=pg npm run vona :bin:test -- test-pay/test/paymentSession.test.ts test-pay/test/payMock.test.ts test-pay/test/outbox.test.ts test-pay/test/webhook.test.ts --flavor=normal
39
+ working-directory: vona
37
40
  - name: run Commerce stock contention gate
38
41
  run: |
39
42
  DATABASE_DEFAULT_CLIENT=pg npm run vona :bin:test -- commerce-trade/test/stockBalance.test.ts commerce-trade/test/stockReservation.test.ts commerce-trade/test/stockAudit.test.ts --flavor=normal
@@ -27,6 +27,9 @@ jobs:
27
27
  version: 11.5.2
28
28
  - name: init
29
29
  run: npm run init
30
+ - name: run A-Pay focused gate
31
+ run: DATABASE_DEFAULT_CLIENT=sqlite3 npm run vona :bin:test -- test-pay/test/paymentSession.test.ts test-pay/test/payMock.test.ts test-pay/test/outbox.test.ts test-pay/test/webhook.test.ts --flavor=normal
32
+ working-directory: vona
30
33
  - name: run Commerce payment, shipment, and refund lifecycle gate
31
34
  run: DATABASE_DEFAULT_CLIENT=sqlite3 npm run vona :bin:test -- commerce-trade/test/paymentOutcome.test.ts commerce-trade/test/reservationExpiry.test.ts commerce-trade/test/shipment.test.ts commerce-trade/test/refundLifecycle.test.ts --flavor=normal
32
35
  working-directory: vona
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.1.126
4
+
5
+ ### Features
6
+
7
+ - Add and update skills for the cabloy worktree environment.
8
+ - Add payment capabilities and related tests.
9
+ - Add DTO inference support.
10
+ - Add `$Dto.get` rules.
11
+ - Update application capabilities and workflows.
12
+
13
+ ### Improvements
14
+
15
+ - Refactor DTO inference handling.
16
+ - Refactor training-related modules.
17
+
3
18
  ## 5.1.125
4
19
 
5
20
  ### Features
package/CLAUDE.md CHANGED
@@ -58,7 +58,7 @@ Before inventing a custom implementation path:
58
58
  - Default to establishing such query state during render. Use `disableSuspenseOnInit: true` only for relatively stable query-backed state when you want to skip the init-time `query.suspense()` kick; it does not prevent query creation, fetches, or hydration-time rendering. If strict readiness is needed later, wait explicitly at the interaction boundary.
59
59
  - In SSR, keep server HTML and the client's hydration-time initial render equivalent. When server rendering intentionally omits private, cookie-unavailable, or browser-only state, keep the same neutral shell or placeholder through hydration and defer its query/load/render branch to an explicit post-hydration, admission, mounted, or interaction boundary.
60
60
  - Keep repo-wide AI rules in `CLAUDE.md` short and durable; put branching Zova analysis workflows in `.claude/skills/`.
61
- - Do not modify shared environment identity or ports merely to bypass a busy resource. For intentional parallel worktree setup, follow `cabloy-docs/fullstack/parallel-worktree-environment.md`; otherwise wait for the shared resource or ask the user.
61
+ - Do not modify shared environment identity or ports merely to bypass a busy resource. For intentional parallel worktree setup, follow `cabloy-docs/fullstack/parallel-worktree-environment.md`; otherwise wait for the shared resource or ask the user. Create or change worktree-local environment overrides only through the explicitly invoked `cabloy-worktree-environment` skill and its confirmation phase, and only in `vona/env/.env.local` and `zova/env/.env.local`; never modify flavor-, mode-, app-mode-, or runtime-specific `.env.*.local` files. The skill derives the standard `APP_NAME`, `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, `DEV_SERVER_HMR_PORT`, and API-derived `API_BASE_URL` tuple only from Git worktree metadata and fixed port baselines; never read or expose `.env*` content while recommending values. Admin and Web are alternative commands using this shared tuple and must not run concurrently in one worktree; use another linked worktree for concurrent use. Detect the active edition before choosing scripts, and never run `npm run init` as an automatic follow-up.
62
62
  - For SSR theme-sensitive frontend work, detect the active edition marker and UI library before making assumptions. Cabloy Basic currently means DaisyUI + Tailwind CSS assumptions; Cabloy Start currently means Vuetify assumptions.
63
63
  - In Web SSR without cookie-backed theme resolution, do not treat server reads of `$theme.dark`, `$theme.darkMode`, or `$token` as final browser truth. Keep theme-sensitive SSR branching hydration-tolerant or defer final theme-sensitive decisions to the client.
64
64
  - Do not assume Cabloy Basic and Cabloy Start use the same adapter-level SSR theme handoff. Verify the active theme handler and client hydration path before changing SSR theme behavior.
@@ -198,6 +198,7 @@ export default defineConfig({
198
198
  items: [
199
199
  { text: 'Introduction', link: '/backend/introduction' },
200
200
  { text: 'Foundation', link: '/backend/foundation' },
201
+ { text: 'Module Dependencies', link: '/backend/module-dependencies' },
201
202
  { text: 'Backend Essentials', link: '/backend/backend-essentials' },
202
203
  { text: 'Quickstart', link: '/backend/quickstart' },
203
204
  {
@@ -101,8 +101,8 @@ The next source to read is:
101
101
  Representative source facts:
102
102
 
103
103
  - `@Dto<IDtoOptionsStudentSummary>()`
104
- - fields such as `id`, `name`, `mobile`, `level`, `levelTitle`, `description`, `descriptionLength`, and `summaryText`
105
- - `@Api.field(...)` metadata on each field
104
+ - the `ModelStudent` projection supplies `id`, `name`, `mobile`, `level`, and `description`
105
+ - direct `@Api.field(...)` metadata declares the computed `levelTitle`, `descriptionLength`, and `summaryText` fields
106
106
 
107
107
  This file answers the second emission question:
108
108
 
@@ -148,7 +148,9 @@ A practical split is:
148
148
  - use inferred DTOs when the contract closely follows model structure or query shape
149
149
  - wrap inferred DTOs in a named DTO class when reuse or discoverability becomes more important
150
150
 
151
- Advanced inferred DTO shaping can also stay named and reusable through helper options such as `dtoClass`, especially for relation-aware contracts and nested DTO surfaces. For the inference side, see [DTO Infer and Generation](/backend/dto-infer-generation).
151
+ When stable Entity, Model, relation, or query truth already exists, prefer inference first: use `$Dto.*` with `columns`, `include`, or `dtoClass` to define the projection; use `@Dto({ fields })` with `$makeMetadata(...)` for metadata-only differences or `$makeSchema(...)` for schema and validation differences; add an `@Api.field(...)` member only for a genuinely new field absent from the inferred contract. Keep an explicit DTO as a deliberate fallback when no suitable upstream truth exists or the inferred composition is less clear.
152
+
153
+ Advanced inferred DTO shaping can also stay named and reusable through helper options such as `dtoClass`, especially for relation-aware contracts and nested DTO surfaces. `$Dto.get(...)` otherwise keeps the complete model-aware read shape by default; use `columns` or `dtoClass` for a genuine business projection, not merely to remove `iid` or `deleted`. For the canonical authoring sequence, see [Default-first three-layer DTO authoring](/backend/dto-infer-generation#default-first-three-layer-dto-authoring) and [Default read shape versus a public projection](/backend/dto-infer-generation#default-read-shape-versus-a-public-projection).
152
154
 
153
155
  ## Relationship to ORM and controller contracts
154
156
 
@@ -166,12 +168,13 @@ That means DTO design should often be read together with:
166
168
 
167
169
  When creating DTOs:
168
170
 
169
- 1. prefer reuse through mapped-class helpers when the shape is derived from existing classes
170
- 2. keep DTO validation and OpenAPI concerns aligned through `@Api.field`
171
- 3. decide whether the contract should be an explicit DTO class or an inferred DTO
172
- 4. avoid re-declaring fields manually if Vona’s DTO-generation or class-derivation tools already solve the problem
173
- 5. treat DTO design as part of the contract between backend handlers, models, and frontend integration
174
- 6. choose explicit DTOs when named long-lived contracts matter, and inferred DTOs when the model/query shape already expresses the contract clearly
171
+ 1. check whether an Entity, Model, relation, or query shape already provides suitable upstream contract truth
172
+ 2. define the inferred projection before redeclaring fields: choose the `$Dto.*` helper and, where needed, `columns`, `include`, or `dtoClass`
173
+ 3. use `$makeMetadata(...)` for metadata-only refinement and `$makeSchema(...)` for schema or validation refinement of an inferred field
174
+ 4. use `@Api.field(...)` for a genuinely new field, not as a second declaration of an inferred field
175
+ 5. keep DTO validation and OpenAPI concerns aligned, and keep the final structure-defining schema last when using schema-like composition
176
+ 6. decide whether the contract should remain inferred, be wrapped in a named inferred DTO, or deliberately fall back to an explicit DTO
177
+ 7. treat DTO design as part of the contract between backend handlers, models, and frontend integration
175
178
 
176
179
  ## Where to read next
177
180